Mercurial > illumos > illumos-gate
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>
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, ®, &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, ®, &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 *);