summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/cmd/isainfo/isainfo.c29
-rw-r--r--usr/src/cmd/ptools/pargs/pargs.c23
-rw-r--r--usr/src/cmd/sgs/elfdump/common/corenote.c23
-rw-r--r--usr/src/cmd/sgs/libconv/common/corenote.c10
-rw-r--r--usr/src/cmd/sgs/libconv/common/corenote.msg1
-rw-r--r--usr/src/cmd/sgs/rtld/amd64/_setup.c14
-rw-r--r--usr/src/cmd/sgs/rtld/common/_rtld.h5
-rw-r--r--usr/src/cmd/sgs/rtld/common/setup.c8
-rw-r--r--usr/src/cmd/sgs/rtld/i386/_setup.c14
-rw-r--r--usr/src/cmd/sgs/rtld/sparc/_setup.c16
-rw-r--r--usr/src/cmd/sgs/rtld/sparcv9/_setup.c14
-rw-r--r--usr/src/common/dis/i386/dis_tables.c39
-rw-r--r--usr/src/common/elfcap/elfcap.c25
-rw-r--r--usr/src/common/elfcap/elfcap.h3
-rw-r--r--usr/src/lib/libc/port/gen/getisax.c24
-rw-r--r--usr/src/uts/common/exec/elf/elf.c20
-rw-r--r--usr/src/uts/common/io/cpuid_drv.c19
-rw-r--r--usr/src/uts/common/os/exec.c5
-rw-r--r--usr/src/uts/common/sys/auxv.h12
-rw-r--r--usr/src/uts/common/sys/auxv_386.h9
-rw-r--r--usr/src/uts/common/sys/cpuid_drv.h9
-rw-r--r--usr/src/uts/common/sys/user.h9
-rw-r--r--usr/src/uts/i86pc/os/cpuid.c35
-rw-r--r--usr/src/uts/i86pc/os/mp_startup.c5
-rw-r--r--usr/src/uts/intel/ia32/os/archdep.c32
-rw-r--r--usr/src/uts/intel/sys/x86_archext.h15
26 files changed, 328 insertions, 90 deletions
diff --git a/usr/src/cmd/isainfo/isainfo.c b/usr/src/cmd/isainfo/isainfo.c
index fb7ef19c97..adf2f14dc9 100644
--- a/usr/src/cmd/isainfo/isainfo.c
+++ b/usr/src/cmd/isainfo/isainfo.c
@@ -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 @@ static void
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 @@ report_hwcap(int d, const char *isa)
linecnt = printf("\t");
linecnt += printf("%s ", p);
}
+
if (linecnt != 0)
(void) printf("\n");
}
diff --git a/usr/src/cmd/ptools/pargs/pargs.c b/usr/src/cmd/ptools/pargs/pargs.c
index b98422d6b1..30c60ca3c3 100644
--- a/usr/src/cmd/ptools/pargs/pargs.c
+++ b/usr/src/cmd/ptools/pargs/pargs.c
@@ -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 @@ at_hwcap(long val, char *instr, size_t n, char *str)
/*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 @@ static struct aux_id aux_arr[] = {
{ 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 },
diff --git a/usr/src/cmd/sgs/elfdump/common/corenote.c b/usr/src/cmd/sgs/elfdump/common/corenote.c
index 81c293572b..243fd12f22 100644
--- a/usr/src/cmd/sgs/elfdump/common/corenote.c
+++ b/usr/src/cmd/sgs/elfdump/common/corenote.c
@@ -432,6 +432,7 @@ dump_auxv(note_state_t *state, const char *title)
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 @@ dump_auxv(note_state_t *state, const char *title)
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:
diff --git a/usr/src/cmd/sgs/libconv/common/corenote.c b/usr/src/cmd/sgs/libconv/common/corenote.c
index 2fd96b3931..352dd3ee70 100644
--- a/usr/src/cmd/sgs/libconv/common/corenote.c
+++ b/usr/src/cmd/sgs/libconv/common/corenote.c
@@ -102,19 +102,19 @@ conv_cnote_auxv_type(Word type, Conv_fmt_flags_t fmt_flags,
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));
diff --git a/usr/src/cmd/sgs/libconv/common/corenote.msg b/usr/src/cmd/sgs/libconv/common/corenote.msg
index e074c19301..36925e1039 100644
--- a/usr/src/cmd/sgs/libconv/common/corenote.msg
+++ b/usr/src/cmd/sgs/libconv/common/corenote.msg
@@ -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"
diff --git a/usr/src/cmd/sgs/rtld/amd64/_setup.c b/usr/src/cmd/sgs/rtld/amd64/_setup.c
index faf4bb91b3..cd47f3b91f 100644
--- a/usr/src/cmd/sgs/rtld/amd64/_setup.c
+++ b/usr/src/cmd/sgs/rtld/amd64/_setup.c
@@ -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 @@ _setup(Boot *ebp, Dyn *ld_dyn)
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 @@ _setup(Boot *ebp, Dyn *ld_dyn)
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 @@ _setup(Boot *ebp, Dyn *ld_dyn)
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);
}
diff --git a/usr/src/cmd/sgs/rtld/common/_rtld.h b/usr/src/cmd/sgs/rtld/common/_rtld.h
index d99b86cf82..3cbb58fe25 100644
--- a/usr/src/cmd/sgs/rtld/common/_rtld.h
+++ b/usr/src/cmd/sgs/rtld/common/_rtld.h
@@ -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 void set_dirs(Alist **, Spath_defn *, uint_t);
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 *);
diff --git a/usr/src/cmd/sgs/rtld/common/setup.c b/usr/src/cmd/sgs/rtld/common/setup.c
index c5d2a2671e..862bb7d61f 100644
--- a/usr/src/cmd/sgs/rtld/common/setup.c
+++ b/usr/src/cmd/sgs/rtld/common/setup.c
@@ -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 @@ Rt_map *
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 @@ setup(char **envp, auxv_t *auxv, Word _flags, char *_platform, int _syspagsz,
*/
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];
}
/*
diff --git a/usr/src/cmd/sgs/rtld/i386/_setup.c b/usr/src/cmd/sgs/rtld/i386/_setup.c
index 0b46e83e86..3dc934852f 100644
--- a/usr/src/cmd/sgs/rtld/i386/_setup.c
+++ b/usr/src/cmd/sgs/rtld/i386/_setup.c
@@ -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 @@ _setup(Boot *ebp, Dyn *ld_dyn)
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 @@ _setup(Boot *ebp, Dyn *ld_dyn)
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 @@ _setup(Boot *ebp, Dyn *ld_dyn)
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);
}
diff --git a/usr/src/cmd/sgs/rtld/sparc/_setup.c b/usr/src/cmd/sgs/rtld/sparc/_setup.c
index cea3a3dc1d..0bd3e57944 100644
--- a/usr/src/cmd/sgs/rtld/sparc/_setup.c
+++ b/usr/src/cmd/sgs/rtld/sparc/_setup.c
@@ -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 @@ _setup(Boot *ebp, Dyn *ld_dyn)
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 @@ _setup(Boot *ebp, Dyn *ld_dyn)
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 @@ _setup(Boot *ebp, Dyn *ld_dyn)
_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);
}
diff --git a/usr/src/cmd/sgs/rtld/sparcv9/_setup.c b/usr/src/cmd/sgs/rtld/sparcv9/_setup.c
index 7aa1636b5b..21cdbef1c7 100644
--- a/usr/src/cmd/sgs/rtld/sparcv9/_setup.c
+++ b/usr/src/cmd/sgs/rtld/sparcv9/_setup.c
@@ -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 @@ _setup(Boot *ebp, Dyn *ld_dyn)
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 @@ _setup(Boot *ebp, Dyn *ld_dyn)
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 @@ _setup(Boot *ebp, Dyn *ld_dyn)
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);
}
diff --git a/usr/src/common/dis/i386/dis_tables.c b/usr/src/common/dis/i386/dis_tables.c
index 87158fa2eb..8258096e43 100644
--- a/usr/src/common/dis/i386/dis_tables.c
+++ b/usr/src/common/dis/i386/dis_tables.c
@@ -32,7 +32,6 @@
/* Copyright (c) 1988 AT&T */
/* All Rights Reserved */
-
#include "dis_tables.h"
/* BEGIN CSTYLED */
@@ -541,6 +540,16 @@ const instable_t dis_op0FC7[8] = {
};
/*
+ * 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 @@ const instable_t dis_opAVX660F38[256] = {
/* [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 @@ const instable_t dis_opAVX660F3A[256] = {
/* [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 @@ dtrace_disx86(dis86_t *x, uint_t cpu_mode)
* 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 @@ dtrace_disx86(dis86_t *x, uint_t cpu_mode)
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 @@ L_VEX_MX:
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 @@ L_VEX_MX:
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);
diff --git a/usr/src/common/elfcap/elfcap.c b/usr/src/common/elfcap/elfcap.c
index 3cd9b4aedc..b062071d90 100644
--- a/usr/src/common/elfcap/elfcap.c
+++ b/usr/src/common/elfcap/elfcap.c
@@ -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 hw1_386[ELFCAP_NUM_HW1_386] = {
}
};
+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 @@ elfcap_hw1_to_str(elfcap_style_t style, elfcap_mask_t val, char *str,
}
/*
- * 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 @@ elfcap_hw2_to_str(elfcap_style_t style, elfcap_mask_t val, char *str,
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 @@ elfcap_hw1_from_str(elfcap_style_t style, const char *str, ushort_t mach)
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);
}
diff --git a/usr/src/common/elfcap/elfcap.h b/usr/src/common/elfcap/elfcap.h
index 3d09397ee5..1a71e75a5b 100644
--- a/usr/src/common/elfcap/elfcap.h
+++ b/usr/src/common/elfcap/elfcap.h
@@ -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 @@ typedef enum {
#define ELFCAP_NUM_SF1 3
#define ELFCAP_NUM_HW1_SPARC 17
#define ELFCAP_NUM_HW1_386 32
+#define ELFCAP_NUM_HW2_386 2
/*
diff --git a/usr/src/lib/libc/port/gen/getisax.c b/usr/src/lib/libc/port/gen/getisax.c
index db0d171412..c721528fb3 100644
--- a/usr/src/lib/libc/port/gen/getisax.c
+++ b/usr/src/lib/libc/port/gen/getisax.c
@@ -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 @@ getisax(uint32_t *array, uint_t n)
{
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);
}
diff --git a/usr/src/uts/common/exec/elf/elf.c b/usr/src/uts/common/exec/elf/elf.c
index cc78a40bbc..ab46ff3924 100644
--- a/usr/src/uts/common/exec/elf/elf.c
+++ b/usr/src/uts/common/exec/elf/elf.c
@@ -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 @@ elfexec(vnode_t *vp, execa_t *uap, uarg_t *args, intpdata_t *idatap,
* 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 @@ elfexec(vnode_t *vp, execa_t *uap, uarg_t *args, intpdata_t *idatap,
*
* 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 @@ elfexec(vnode_t *vp, execa_t *uap, uarg_t *args, intpdata_t *idatap,
*
* 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 @@ elfexec(vnode_t *vp, execa_t *uap, uarg_t *args, intpdata_t *idatap,
* (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) {
/*
diff --git a/usr/src/uts/common/io/cpuid_drv.c b/usr/src/uts/common/io/cpuid_drv.c
index 084c916a68..4f65c5ee09 100644
--- a/usr/src/uts/common/io/cpuid_drv.c
+++ b/usr/src/uts/common/io/cpuid_drv.c
@@ -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 @@ cpuid_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *cr, int *rval)
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);
diff --git a/usr/src/uts/common/os/exec.c b/usr/src/uts/common/os/exec.c
index ad77d56560..994c034fe0 100644
--- a/usr/src/uts/common/os/exec.c
+++ b/usr/src/uts/common/os/exec.c
@@ -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 execsetid(struct vnode *, struct vattr *, uid_t *, uid_t *,
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)
diff --git a/usr/src/uts/common/sys/auxv.h b/usr/src/uts/common/sys/auxv.h
index 34ace0ec93..fac0f359b2 100644
--- a/usr/src/uts/common/sys/auxv.h
+++ b/usr/src/uts/common/sys/auxv.h
@@ -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 @@ typedef struct {
* 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 @@ typedef struct {
* 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 @@ extern uint_t getisax(uint32_t *, uint_t);
#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.
diff --git a/usr/src/uts/common/sys/auxv_386.h b/usr/src/uts/common/sys/auxv_386.h
index 2d5deed980..d25626e7f3 100644
--- a/usr/src/uts/common/sys/auxv_386.h
+++ b/usr/src/uts/common/sys/auxv_386.h
@@ -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 @@ extern "C" {
"\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
diff --git a/usr/src/uts/common/sys/cpuid_drv.h b/usr/src/uts/common/sys/cpuid_drv.h
index 3c9271b2fb..42cc9a7a32 100644
--- a/usr/src/uts/common/sys/cpuid_drv.h
+++ b/usr/src/uts/common/sys/cpuid_drv.h
@@ -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 @@ extern "C" {
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_hwcap {
struct cpuid_get_hwcap32 {
caddr32_t cgh_archname;
- uint32_t cgh_hwcap;
+ uint32_t cgh_hwcap[2];
};
#endif /* _SYSCALL32_IMPL */
diff --git a/usr/src/uts/common/sys/user.h b/usr/src/uts/common/sys/user.h
index 9061fa5a23..a7bff8dd52 100644
--- a/usr/src/uts/common/sys/user.h
+++ b/usr/src/uts/common/sys/user.h
@@ -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 @@ typedef struct { /* kernel syscall set type */
* 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;
diff --git a/usr/src/uts/i86pc/os/cpuid.c b/usr/src/uts/i86pc/os/cpuid.c
index 10946474dd..b5cb7674c4 100644
--- a/usr/src/uts/i86pc/os/cpuid.c
+++ b/usr/src/uts/i86pc/os/cpuid.c
@@ -161,7 +161,9 @@ static char *x86_feature_names[NUM_X86_FEATURES] = {
"avx",
"vmx",
"svm",
- "topoext"
+ "topoext",
+ "f16c",
+ "rdrand"
};
boolean_t
@@ -1155,6 +1157,7 @@ cpuid_pass1(cpu_t *cpu, uchar_t *featureset)
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 @@ cpuid_pass1(cpu_t *cpu, uchar_t *featureset)
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 @@ cpuid_pass1(cpu_t *cpu, uchar_t *featureset)
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 @@ cpuid_pass2(cpu_t *cpu)
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 @@ cpuid_pass3(cpu_t *cpu)
* 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_pass4(cpu_t *cpu)
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 @@ cpuid_pass4(cpu_t *cpu)
(*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 @@ cpuid_pass4(cpu_t *cpu)
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 @@ cpuid_pass4(cpu_t *cpu)
pass4_done:
cpi->cpi_pass = 4;
- return (hwcap_flags);
+ if (hwcap_out != NULL) {
+ hwcap_out[0] = hwcap_flags;
+ hwcap_out[1] = hwcap_flags_2;
+ }
}
diff --git a/usr/src/uts/i86pc/os/mp_startup.c b/usr/src/uts/i86pc/os/mp_startup.c
index 588d38bb7a..f4289939fe 100644
--- a/usr/src/uts/i86pc/os/mp_startup.c
+++ b/usr/src/uts/i86pc/os/mp_startup.c
@@ -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 @@ mp_startup_common(boolean_t boot)
cpuid_pass2(cp);
cpuid_pass3(cp);
- (void) cpuid_pass4(cp);
+ cpuid_pass4(cp, NULL);
/*
* Correct cpu_idstr and cpu_brandstr on target CPU after
diff --git a/usr/src/uts/intel/ia32/os/archdep.c b/usr/src/uts/intel/ia32/os/archdep.c
index 423b94a13e..f5663b92d0 100644
--- a/usr/src/uts/intel/ia32/os/archdep.c
+++ b/usr/src/uts/intel/ia32/os/archdep.c
@@ -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 @@ elfheadcheck(
}
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 @@ uint_t auxv_hwcap32_exclude = 0; /* ditto for 32-bit apps */
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 @@ bind_hwcap(void)
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 @@ bind_hwcap(void)
* 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 @@ bind_hwcap(void)
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
}
diff --git a/usr/src/uts/intel/sys/x86_archext.h b/usr/src/uts/intel/sys/x86_archext.h
index f1a77e945a..037bb84298 100644
--- a/usr/src/uts/intel/sys/x86_archext.h
+++ b/usr/src/uts/intel/sys/x86_archext.h
@@ -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 @@ extern "C" {
#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 @@ extern "C" {
#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 @@ extern "C" {
#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_free_space(struct cpu *);
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 *);