summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan McDonald <danmcd@joyent.com>2021-02-09 09:49:56 -0500
committerDan McDonald <danmcd@joyent.com>2021-02-09 09:49:56 -0500
commit83fbed6f664b5d3ca3e61c896d9b180b3cd06202 (patch)
tree8bdcf28083ba98c566d105d0c93eb88d765fef83
parent4d320273bce348b033c83d1742ce873c351c16d4 (diff)
parent9250eb132f1fc3950c838b7a5746f1bcdac7eba1 (diff)
downloadillumos-joyent-83fbed6f664b5d3ca3e61c896d9b180b3cd06202.tar.gz
[illumos-gate merge]
commit 9250eb132f1fc3950c838b7a5746f1bcdac7eba1 13375 bhyve should expose invariant TSC 13381 support TSC offsets on AMD bhyve 13382 consolidate MSR emulation in bhyve commit a8facf2616619e45ebfa3de1fa4def4b433a0245 13481 ld(1) should skip GCC local aliases when building symsort sections commit a8e9db1c816399e66d096a343815a6e845a7a0cd 13299 File mtime changes twice, when file is modified using SMB server commit f74a127feb6111d3b6890ae374a142eda1fd4e3e 13227 SMB server serializes writes where it should not commit a32b2b2a1fc68ee509dbff96287ca2c319495b53 13480 wsdiff didn't use to care about directory naming commit 735d82f0eed0b47d38f86a63ede0e523c18eab09 13479 /etc/ksh.kshrc prompt could work with set nounset commit f4fe62a3c26a7b15283589c57a3c10ed9695b529 13497 libresolv: symbol 'h_errno' is multiply-defined commit 13904da86c95bce026575f75b430075604bb28e4 13474 pbchk could lint shell scripts
-rw-r--r--usr/src/cmd/nsadmin/ksh.kshrc10
-rw-r--r--usr/src/cmd/sgs/libld/common/libld.msg2
-rw-r--r--usr/src/cmd/sgs/libld/common/syms.c65
-rw-r--r--usr/src/cmd/sgs/tools/SUNWonld-README1
-rw-r--r--usr/src/compat/bhyve/amd64/machine/cpufunc.h12
-rw-r--r--usr/src/lib/libresolv/res_query.c4
-rw-r--r--usr/src/pkg/manifests/developer-build-onbld.mf12
-rw-r--r--usr/src/tools/onbld/Checks/Makefile.com3
-rw-r--r--usr/src/tools/onbld/Checks/ShellLint.py42
-rw-r--r--usr/src/tools/onbld/Checks/__init__.py2
-rw-r--r--usr/src/tools/scripts/git-pbchk.py25
-rw-r--r--usr/src/tools/scripts/wsdiff.py109
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_common_open.c2
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_fsops.c2
-rw-r--r--usr/src/uts/common/smbsrv/smb_ktypes.h1
-rw-r--r--usr/src/uts/i86pc/io/vmm/amd/svm.c15
-rw-r--r--usr/src/uts/i86pc/io/vmm/amd/svm_msr.c19
-rw-r--r--usr/src/uts/i86pc/io/vmm/intel/vmx.c10
-rw-r--r--usr/src/uts/i86pc/io/vmm/intel/vmx_msr.c27
-rw-r--r--usr/src/uts/i86pc/io/vmm/sys/vmm_kernel.h4
-rw-r--r--usr/src/uts/i86pc/io/vmm/vmm.c148
-rw-r--r--usr/src/uts/i86pc/io/vmm/vmm_sol_glue.c18
-rw-r--r--usr/src/uts/i86pc/io/vmm/x86.c35
23 files changed, 388 insertions, 180 deletions
diff --git a/usr/src/cmd/nsadmin/ksh.kshrc b/usr/src/cmd/nsadmin/ksh.kshrc
index ea3826223d..568857311c 100644
--- a/usr/src/cmd/nsadmin/ksh.kshrc
+++ b/usr/src/cmd/nsadmin/ksh.kshrc
@@ -67,17 +67,17 @@ fi
# unless PS1 gets "unset" first.
# - Make sure to use absolute paths (e.g. /usr/bin/hostname) to make
# sure PS1 works in cases where PATH does not contain /usr/bin/
-if [[ "$(set)" != ~(E)PS1= && "${PS1}" == '' ]] ; then
+if [[ "$(set)" != ~(E)PS1= && -z "${PS1-}" ]] ; then
PS1='$(set +o xtrace +o errexit
- printf "%*s\r%s" COLUMNS ""
- printf "%s@%s:" "${LOGNAME}" "$(/usr/bin/hostname)"
+ [[ -v COLUMNS ]] && printf "%*s\r%s" COLUMNS ""
+ printf "%s@%s:" "${LOGNAME-}" "$(/usr/bin/hostname)"
ellip="${
- [[ "${LC_ALL}/${LANG}" == ~(Elr)(.*UTF-8/.*|/.*UTF-8) ]] &&
+ [[ "${LC_ALL-}/${LANG-}" == ~(Elr)(.*UTF-8/.*|/.*UTF-8) ]] &&
printf "\u[2026]\n" || print "..." ; }"
p="${PWD/~(El)${HOME}/\~}"
(( ${#p} > 30 )) &&
print -r -n -- "${ellip}${p:${#p}-30:30}" ||
print -r -n -- "${p}"
- [[ "${LOGNAME}" == "root" ]] && print -n "# " || print -n "\$ "
+ [[ "${LOGNAME-}" == "root" ]] && print -n "# " || print -n "\$ "
)'
fi
diff --git a/usr/src/cmd/sgs/libld/common/libld.msg b/usr/src/cmd/sgs/libld/common/libld.msg
index 390fc7e31a..182afd2478 100644
--- a/usr/src/cmd/sgs/libld/common/libld.msg
+++ b/usr/src/cmd/sgs/libld/common/libld.msg
@@ -883,6 +883,8 @@
@ MSG_SYM_L_START "START_"
@ MSG_SYM_L_START_U "_START_"
+@ MSG_SYM_LOCALALIAS ".localalias"
+
@ MSG_SYM_SECBOUND_START "__start_"
@ MSG_SYM_SECBOUND_STOP "__stop_"
diff --git a/usr/src/cmd/sgs/libld/common/syms.c b/usr/src/cmd/sgs/libld/common/syms.c
index ed2191761b..a40f8ae5cd 100644
--- a/usr/src/cmd/sgs/libld/common/syms.c
+++ b/usr/src/cmd/sgs/libld/common/syms.c
@@ -33,6 +33,9 @@
#define ELF_TARGET_AMD64
+/* We deliberately choose a locale unaware ctype */
+#include <sys/ctype.h>
+
#include <stdio.h>
#include <string.h>
#include <debug.h>
@@ -318,6 +321,41 @@ ld_sym_find(const char *name, Word hash, avl_index_t *where, Ofl_desc *ofl)
}
/*
+ * GCC sometimes emits local aliases for otherwise global symbols, such that
+ * it has a guaranteed way to refer to a symbol from the current object
+ * regardless of interposition.
+ *
+ * The only way we can match on these aliases is by them ending either
+ * ".localalias" or ".localalias.N" where N is any integer.
+ */
+static inline Boolean
+is_gcc_localalias(Sym_desc *sdp)
+{
+ char *p;
+
+ if (ELF_ST_BIND(sdp->sd_sym->st_info) != STB_LOCAL)
+ return (FALSE);
+
+ if ((p = strstr(sdp->sd_name, MSG_ORIG(MSG_SYM_LOCALALIAS))) != NULL) {
+ p += MSG_SYM_LOCALALIAS_SIZE;
+ switch (*p++) {
+ case '\0': /* unnumbered */
+ return (TRUE);
+ case '.': /* numbered? */
+ if (*p == '\0') /* no integer */
+ return (FALSE);
+ while (ISDIGIT(*p)) /* skip integer */
+ p++;
+ if (*p != '\0') /* non-integer chars */
+ return (FALSE);
+ return (TRUE);
+ }
+ }
+
+ return (FALSE);
+}
+
+/*
* Enter a new symbol into the link editors internal symbol table.
* If the symbol is from an input file, information regarding the input file
* and input section is also recorded. Otherwise (file == NULL) the symbol
@@ -2040,7 +2078,6 @@ ld_sym_process(Is_desc *isc, Ifl_desc *ifl, Ofl_desc *ofl)
uchar_t osabi = ifl->ifl_ehdr->e_ident[EI_OSABI];
Half mach = ifl->ifl_ehdr->e_machine;
Half etype = ifl->ifl_ehdr->e_type;
- int etype_rel;
const char *symsecname, *strsecname;
Word symsecndx;
avl_index_t where;
@@ -2117,13 +2154,12 @@ ld_sym_process(Is_desc *isc, Ifl_desc *ifl, Ofl_desc *ofl)
if ((ifl->ifl_oldndx = libld_malloc((size_t)(total *
sizeof (Sym_desc *)))) == NULL)
return (S_ERROR);
- etype_rel = (etype == ET_REL);
- if (etype_rel && local) {
+ if ((etype == ET_REL) && (local != 0)) {
if ((ifl->ifl_locs =
libld_calloc(sizeof (Sym_desc), local)) == NULL)
return (S_ERROR);
/* LINTED */
- ifl->ifl_locscnt = (Word)local;
+ ifl->ifl_locscnt = local;
}
ifl->ifl_symscnt = total;
@@ -2131,7 +2167,7 @@ ld_sym_process(Is_desc *isc, Ifl_desc *ifl, Ofl_desc *ofl)
* If there are local symbols to save add them to the symbol table
* index array.
*/
- if (local) {
+ if (local != 0) {
int allow_ldynsym = OFL_ALLOW_LDYNSYM(ofl);
Sym_desc *last_file_sdp = NULL;
int last_file_ndx = 0;
@@ -2215,8 +2251,9 @@ ld_sym_process(Is_desc *isc, Ifl_desc *ifl, Ofl_desc *ofl)
/* Will not appear in output object */
symtab_enter = 0;
}
- } else if (etype == ET_DYN)
+ } else if (etype == ET_DYN) {
continue;
+ }
/*
* Fill in the remaining symbol descriptor information.
@@ -2313,7 +2350,7 @@ ld_sym_process(Is_desc *isc, Ifl_desc *ifl, Ofl_desc *ofl)
* to make sure the section boundaries encompass it.
* If they don't, the ELF file is corrupt.
*/
- if (etype_rel) {
+ if (etype == ET_REL) {
if (SYM_LOC_BADADDR(sdp, sym, type)) {
issue_badaddr_msg(ifl, ofl, sdp,
sym, shndx);
@@ -2349,6 +2386,14 @@ ld_sym_process(Is_desc *isc, Ifl_desc *ifl, Ofl_desc *ofl)
}
}
+ /*
+ * If this symbol comes from a relocatable object and
+ * looks like a GCC local function alias, don't
+ * include it in dynsort sections, since the global
+ * name will always be preferable.
+ */
+ if ((etype == ET_REL) && is_gcc_localalias(sdp))
+ sdp->sd_flags |= FLG_SY_NODYNSORT;
/*
* Sanity check for TLS
@@ -2729,10 +2774,10 @@ ld_sym_process(Is_desc *isc, Ifl_desc *ifl, Ofl_desc *ofl)
if ((sdp = ld_sym_enter(name, nsym, hash, ifl, ofl, ndx,
shndx, sdflags, &where)) == (Sym_desc *)S_ERROR)
return (S_ERROR);
-
} else if (ld_sym_resolve(sdp, nsym, ifl, ofl, ndx, shndx,
- sdflags) == S_ERROR)
+ sdflags) == S_ERROR) {
return (S_ERROR);
+ }
/*
* Now that we have a symbol descriptor, retain the descriptor
@@ -2790,7 +2835,7 @@ ld_sym_process(Is_desc *isc, Ifl_desc *ifl, Ofl_desc *ofl)
* case, we don't check it, because it was already checked
* as part of its own file.
*/
- if (etype_rel && (sdp->sd_file == ifl)) {
+ if ((etype == ET_REL) && (sdp->sd_file == ifl)) {
Sym *tsym = sdp->sd_sym;
if (SYM_LOC_BADADDR(sdp, tsym,
diff --git a/usr/src/cmd/sgs/tools/SUNWonld-README b/usr/src/cmd/sgs/tools/SUNWonld-README
index 731e52c973..a414a6bfe8 100644
--- a/usr/src/cmd/sgs/tools/SUNWonld-README
+++ b/usr/src/cmd/sgs/tools/SUNWonld-README
@@ -1669,3 +1669,4 @@ Bugid Risk Synopsis
10581 ld(1) should know kernel modules are a thing
11057 hidden undefined weak symbols should not leave relocations
11067 debug statistics crash ld(1) when -z allextract
+13481 ld(1) should skip GCC local aliases when building symsort sections
diff --git a/usr/src/compat/bhyve/amd64/machine/cpufunc.h b/usr/src/compat/bhyve/amd64/machine/cpufunc.h
index bb79ac3ce9..134107ef39 100644
--- a/usr/src/compat/bhyve/amd64/machine/cpufunc.h
+++ b/usr/src/compat/bhyve/amd64/machine/cpufunc.h
@@ -112,6 +112,9 @@ read_rflags(void)
return (rf);
}
+/* Equivalent to the FreeBSD rdtsc(), but with any necessary per-cpu offset */
+uint64_t rdtsc_offset(void);
+
static __inline uint64_t
rdmsr(u_int msr)
{
@@ -121,15 +124,6 @@ rdmsr(u_int msr)
return (low | ((uint64_t)high << 32));
}
-static __inline uint64_t
-rdtsc(void)
-{
- extern hrtime_t tsc_gethrtimeunscaled_delta(void);
-
- /* Get the TSC reading with any needed synch offset applied */
- return ((uint64_t)tsc_gethrtimeunscaled_delta());
-}
-
static __inline void
wrmsr(u_int msr, uint64_t newval)
{
diff --git a/usr/src/lib/libresolv/res_query.c b/usr/src/lib/libresolv/res_query.c
index 1c4d95b7c6..0ee63f7fcd 100644
--- a/usr/src/lib/libresolv/res_query.c
+++ b/usr/src/lib/libresolv/res_query.c
@@ -26,7 +26,7 @@
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
-/* All Rights Reserved */
+/* All Rights Reserved */
/*
* University Copyright- Copyright (c) 1982, 1986, 1988
@@ -58,8 +58,6 @@
#define MAXPACKET 1024
#endif
-int h_errno;
-
/*
* Formulate a normal query, send, and await answer.
* Returned answer is placed in supplied buffer "answer".
diff --git a/usr/src/pkg/manifests/developer-build-onbld.mf b/usr/src/pkg/manifests/developer-build-onbld.mf
index cfedad950b..190ada0290 100644
--- a/usr/src/pkg/manifests/developer-build-onbld.mf
+++ b/usr/src/pkg/manifests/developer-build-onbld.mf
@@ -196,6 +196,9 @@ $(python3tools_ONLY)file \
path=opt/onbld/lib/python$(PYTHON3_VERSION)/onbld/Checks/ProcessCheck.py \
mode=0444
$(python3tools_ONLY)file \
+ path=opt/onbld/lib/python$(PYTHON3_VERSION)/onbld/Checks/ShellLint.py \
+ mode=0444
+$(python3tools_ONLY)file \
path=opt/onbld/lib/python$(PYTHON3_VERSION)/onbld/Checks/SpellCheck.py \
mode=0444
$(python3tools_ONLY)file \
@@ -241,6 +244,9 @@ $(python3tools_ONLY)file \
path=opt/onbld/lib/python$(PYTHON3_VERSION)/onbld/Checks/__pycache__/ProcessCheck.cpython$(PYTHON3_PKGVERS).pyc \
mode=0444
$(python3tools_ONLY)file \
+ path=opt/onbld/lib/python$(PYTHON3_VERSION)/onbld/Checks/__pycache__/ShellLint.cpython$(PYTHON3_PKGVERS).pyc \
+ mode=0444
+$(python3tools_ONLY)file \
path=opt/onbld/lib/python$(PYTHON3_VERSION)/onbld/Checks/__pycache__/SpellCheck.cpython$(PYTHON3_PKGVERS).pyc \
mode=0444
$(python3tools_ONLY)file \
@@ -337,6 +343,12 @@ $(python2tools_ONLY)file \
path=opt/onbld/lib/python$(PYTHON_VERSION)/onbld/Checks/ProcessCheck.pyc \
mode=0444
$(python2tools_ONLY)file \
+ path=opt/onbld/lib/python$(PYTHON_VERSION)/onbld/Checks/ShellLint.py \
+ mode=0444
+$(python2tools_ONLY)file \
+ path=opt/onbld/lib/python$(PYTHON_VERSION)/onbld/Checks/ShellLint.pyc \
+ mode=0444
+$(python2tools_ONLY)file \
path=opt/onbld/lib/python$(PYTHON_VERSION)/onbld/Checks/SpellCheck.py \
mode=0444
$(python2tools_ONLY)file \
diff --git a/usr/src/tools/onbld/Checks/Makefile.com b/usr/src/tools/onbld/Checks/Makefile.com
index e8872e8ca8..74f5e2dbfe 100644
--- a/usr/src/tools/onbld/Checks/Makefile.com
+++ b/usr/src/tools/onbld/Checks/Makefile.com
@@ -26,7 +26,7 @@
# Copyright 2010, Richard Lowe
# Copyright 2014 Garrett D'Amore <garrett@damore.org>
# Copyright 2016, Joyent, Inc.
-# Copyright 2018 OmniOS Community Edition (OmniOSce) Association.
+# Copyright 2021 OmniOS Community Edition (OmniOSce) Association.
include $(SRC)/Makefile.master
include ../../../Makefile.tools
@@ -47,6 +47,7 @@ PYSRCS = \
ManLint.py \
Mapfile.py \
ProcessCheck.py \
+ ShellLint.py \
SpellCheck.py \
WsCheck.py \
__init__.py
diff --git a/usr/src/tools/onbld/Checks/ShellLint.py b/usr/src/tools/onbld/Checks/ShellLint.py
new file mode 100644
index 0000000000..06d06f92c8
--- /dev/null
+++ b/usr/src/tools/onbld/Checks/ShellLint.py
@@ -0,0 +1,42 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2021 OmniOS Community Edition (OmniOSce) Association.
+#
+
+#
+# ShellLint, wrap the 'shcomp -n' tool in a python API
+#
+
+import sys
+from onbld.Checks.ProcessCheck import processcheck
+
+def lint(fh, filename=None, output=sys.stderr, **opts):
+ if not filename:
+ filename = fh.name
+
+ options = ['-n', '/dev/stdin', '/dev/null']
+
+ ret, tmpfile = processcheck('shcomp', options, fh, output)
+
+ if tmpfile:
+ for line in tmpfile:
+ if '`...` obsolete' in line:
+ continue
+ ret = 1
+
+ line = line.replace('/dev/stdin', filename)
+ line = line.replace('warning: ', '')
+ output.write(line)
+
+ tmpfile.close()
+ return ret
diff --git a/usr/src/tools/onbld/Checks/__init__.py b/usr/src/tools/onbld/Checks/__init__.py
index a8bca05d55..afde98c7da 100644
--- a/usr/src/tools/onbld/Checks/__init__.py
+++ b/usr/src/tools/onbld/Checks/__init__.py
@@ -27,6 +27,7 @@
# Copyright 2010, Richard Lowe
# Copyright 2014 Garrett D'Amore <garrett@damore.org>
+# Copyright 2021 OmniOS Community Edition (OmniOSce) Association.
#
# The 'checks' package contains various checks that may be run
@@ -42,5 +43,6 @@ __all__ = [
'Keywords',
'ManLint',
'Mapfile',
+ 'ShellLint',
'SpellCheck',
'WsCheck']
diff --git a/usr/src/tools/scripts/git-pbchk.py b/usr/src/tools/scripts/git-pbchk.py
index ec01255c6e..fc9f82b816 100644
--- a/usr/src/tools/scripts/git-pbchk.py
+++ b/usr/src/tools/scripts/git-pbchk.py
@@ -21,7 +21,7 @@
# Copyright (c) 2015, 2016 by Delphix. All rights reserved.
# Copyright 2016 Nexenta Systems, Inc.
# Copyright (c) 2019, Joyent, Inc.
-# Copyright 2020 OmniOS Community Edition (OmniOSce) Association.
+# Copyright 2021 OmniOS Community Edition (OmniOSce) Association.
#
from __future__ import print_function
@@ -57,6 +57,7 @@ sys.path.insert(2, os.path.join(os.path.dirname(__file__), ".."))
from onbld.Scm import Ignore
from onbld.Checks import Comments, Copyright, CStyle, HdrChk, WsCheck
from onbld.Checks import JStyle, Keywords, ManLint, Mapfile, SpellCheck
+from onbld.Checks import ShellLint
class GitError(Exception):
pass
@@ -294,6 +295,26 @@ def manlint(root, parent, flist, output):
ret |= SpellCheck.spellcheck(fh, output=output)
return ret
+def shelllint(root, parent, flist, output):
+ ret = 0
+ output.write("Shell lint:\n")
+
+ def isshell(x):
+ (_, ext) = os.path.splitext(x)
+ if ext in ['.sh', '.ksh']:
+ return True
+ if ext == '':
+ with io.open(x, mode='r', errors='ignore') as fh:
+ if re.match(r'^#.*\bk?sh\b', fh.readline()):
+ return True
+ return False
+
+ for f in flist(isshell):
+ with io.open(f, mode='rb') as fh:
+ ret |= ShellLint.lint(fh, output=output)
+
+ return ret
+
def keywords(root, parent, flist, output):
ret = 0
output.write("SCCS Keywords:\n")
@@ -399,6 +420,7 @@ def nits(root, parent, paths):
keywords,
manlint,
mapfilechk,
+ shelllint,
winnames,
wscheck]
scmds = [symlinks]
@@ -413,6 +435,7 @@ def pbchk(root, parent, paths):
keywords,
manlint,
mapfilechk,
+ shelllint,
winnames,
wscheck]
scmds = [symlinks]
diff --git a/usr/src/tools/scripts/wsdiff.py b/usr/src/tools/scripts/wsdiff.py
index 7b07b273ca..90b6f769c8 100644
--- a/usr/src/tools/scripts/wsdiff.py
+++ b/usr/src/tools/scripts/wsdiff.py
@@ -20,7 +20,7 @@
# CDDL HEADER END
#
# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
-# Copyright 2020 OmniOS Community Edition (OmniOSce) Association.
+# Copyright 2021 OmniOS Community Edition (OmniOSce) Association.
#
#
@@ -113,8 +113,8 @@ wsdiff_path = [ "/usr/bin",
wsdiff_exceptions = [
]
-# Path to genunix, used for CTF diff
-genunix = "/kernel/amd64/genunix"
+# Path to genunix, used for finding the proto root, and for CTF diff
+genunix = "kernel/amd64/genunix"
if PY3:
def getoutput(cmd):
@@ -273,12 +273,10 @@ def diffFileData(tmpf1, tmpf2) :
if binaries :
try:
os.unlink(tmp_od1)
- except OSError as e:
- error("diffFileData: unlink failed %s" % e)
- try:
os.unlink(tmp_od2)
except OSError as e:
- error("diffFileData: unlink failed %s" % e)
+ error("diffFileData: unlink failed {}"
+ .format(e))
except:
error("failed to get output of command: " + dcmd)
@@ -303,9 +301,17 @@ def str_prefix_trunc(s, prefix) :
# e.g. proto.base/root_sparc/usr/src/cmd/prstat => usr/src/cmd/prstat
#
def fnFormat(fn) :
- root_arch_str = "root_" + arch
+ global baseWsRoot, ptchWsRoot
+
+ if len(os.path.commonprefix([fn, baseWsRoot])) == len(baseWsRoot):
+ return fn[len(baseWsRoot) + 1:]
- pos = fn.find(root_arch_str)
+ if len(os.path.commonprefix([fn, ptchWsRoot])) == len(ptchWsRoot):
+ return fn[len(ptchWsRoot) + 1:]
+
+ # Fall back to looking for the expected root_<arch>[-nd] string
+
+ pos = fn.find("root_" + arch)
if pos == -1 :
return fn
@@ -318,11 +324,19 @@ def fnFormat(fn) :
#
# Find the path to a proto root given the name of a file or directory under it
# e.g. proto.base/root_i386-nd/usr/bin => proto.base/root_i386-nd
+# root/usr/bin => root
#
def protoroot(fn):
- root_arch_str = "root_" + arch
+ root = fn
+ while len(root) > 1:
+ if os.path.isfile(os.path.join(root, genunix)):
+ return root
+ root = os.path.dirname(root)
+
+ # genunix was not found, try and determine the root by checking for
+ # the expected root_<arch>[-nd] string
- pos = fn.find(root_arch_str)
+ pos = fn.find("root_" + arch)
if pos == -1:
return None
@@ -332,7 +346,6 @@ def protoroot(fn):
return fn[:pos]
-
#####
# Usage / argument processing
#
@@ -757,14 +770,13 @@ def diff_ctf(f1, f2):
# Find genunix so that it can be used for parent CTF data when
# appropriate.
if diff_ctf.genunix1 is None:
- global genunix, baseRoot, ptchRoot
-
- d1 = protoroot(baseRoot)
- d2 = protoroot(ptchRoot)
- if (d1 and d2 and os.path.isfile(d1 + genunix) and
- os.path.isfile(d2 + genunix)):
- diff_ctf.genunix1 = d1 + genunix
- diff_ctf.genunix2 = d2 + genunix
+ global genunix, baseWsRoot, ptchWsRoot
+
+ if (baseWsRoot and ptchWsRoot and
+ os.path.isfile(os.path.join(baseWsRoot, genunix)) and
+ os.path.isfile(os.path.join(ptchWsRoot, genunix))):
+ diff_ctf.genunix1 = os.path.join(baseWsRoot, genunix)
+ diff_ctf.genunix2 = os.path.join(ptchWsRoot, genunix)
debug("CTF: Found {}".format(diff_ctf.genunix1))
debug("CTF: Found {}".format(diff_ctf.genunix2))
else:
@@ -868,12 +880,9 @@ def diff_elf_section(f1, f2, section, sh_type) :
# remove temp files as we no longer need them
try:
os.unlink(tmpFile1)
- except OSError as e:
- error("diff_elf_section: unlink failed %s" % e)
- try:
os.unlink(tmpFile2)
except OSError as e:
- error("diff_elf_section: unlink failed %s" % e)
+ error("diff_elf_section: unlink failed {}".format(e))
return (data)
@@ -1065,13 +1074,9 @@ def compareArchives(base, ptch, fileType) :
try:
os.makedirs(ArchTmpDir1)
- except OSError as e:
- error("compareArchives: makedir failed %s" % e)
- return -1
- try:
os.makedirs(ArchTmpDir2)
except OSError as e:
- error("compareArchives: makedir failed %s" % e)
+ error("compareArchives: makedir failed {}".format(e))
return -1
# copy over the objects to the temp areas, and
@@ -1244,12 +1249,9 @@ def compareByDumping(base, ptch, quiet, fileType) :
# Remove the temporary files now.
try:
os.unlink(tmpFile1)
- except OSError as e:
- error("compareByDumping: unlink failed %s" % e)
- try:
os.unlink(tmpFile2)
except OSError as e:
- error("compareByDumping: unlink failed %s" % e)
+ error("compareByDumping: unlink failed {}".format(e))
return ret
@@ -1378,8 +1380,8 @@ def main() :
# changed files for worker thread processing
global changedFiles
- global baseRoot
- global ptchRoot
+
+ global baseRoot, ptchRoot, baseWsRoot, ptchWsRoot
# Sort the list of files from a temporary file
global o_sorted
@@ -1410,12 +1412,12 @@ def main() :
log = open(results, "w")
except:
logging = False
- error("failed to open log file: " + log)
+ error("failed to open log file: {}".format(log))
sys.exit(1)
- dateTimeStr= "# %04d-%02d-%02d at %02d:%02d:%02d" % \
- time.localtime()[:6]
v_info("# This file was produced by wsdiff")
+ dateTimeStr= time.strftime('# %Y-%m-%d at %H:%M:%S',
+ time.localtime())
v_info(dateTimeStr)
# Changed files (used only for the sorted case)
@@ -1465,26 +1467,32 @@ def main() :
#
# validate the base and patch paths
#
- if baseRoot[-1] != '/' :
- baseRoot += '/'
-
- if ptchRoot[-1] != '/' :
- ptchRoot += '/'
+ baseRoot = os.path.abspath(baseRoot) + os.sep
+ ptchRoot = os.path.abspath(ptchRoot) + os.sep
if not os.path.exists(baseRoot) :
- error("old proto area: " + baseRoot + " does not exist")
+ error("old proto area: {} does not exist".format(baseRoot))
sys.exit(1)
if not os.path.exists(ptchRoot) :
- error("new proto area: " + ptchRoot + " does not exist")
+ error("new proto area: {} does not exist".format(ptchRoot))
sys.exit(1)
#
+ # attempt to find the workspace root directory for the proto area
+ #
+ baseWsRoot = protoroot(baseRoot)
+ ptchWsRoot = protoroot(ptchRoot)
+ debug("base workspace root: {}".format(baseWsRoot))
+ debug("ptch workspace root: {}".format(ptchWsRoot))
+
+ #
# log some information identifying the run
#
- v_info("Old proto area: " + baseRoot)
- v_info("New proto area: " + ptchRoot)
- v_info("Results file: " + results + "\n")
+ v_info("Old proto area: {}".format(baseRoot))
+ v_info("New proto area: {}".format(ptchRoot))
+ v_info("Results file: {}".format(results))
+ v_info("")
#
# Set up the temporary directories / files
@@ -1495,12 +1503,9 @@ def main() :
tmpDir2 = "/tmp/wsdiff_tmp2_" + str(pid) + "/"
try:
os.makedirs(tmpDir1)
- except OSError as e:
- error("main: makedir failed %s" % e)
- try:
os.makedirs(tmpDir2)
except OSError as e:
- error("main: makedir failed %s" % e)
+ error("main: makedir failed {}".format(e))
# Derive a catalog of new, deleted, and to-be-compared objects
# either from the specified base and patch proto areas, or from
diff --git a/usr/src/uts/common/fs/smbsrv/smb_common_open.c b/usr/src/uts/common/fs/smbsrv/smb_common_open.c
index 2da64f58ab..fb4d46f599 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_common_open.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_common_open.c
@@ -21,7 +21,7 @@
/*
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2020 Nexenta by DDN, Inc. All rights reserved.
+ * Copyright 2020 Tintri by DDN, Inc. All rights reserved.
*/
/*
diff --git a/usr/src/uts/common/fs/smbsrv/smb_fsops.c b/usr/src/uts/common/fs/smbsrv/smb_fsops.c
index 4325d75282..4d6ffa5754 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_fsops.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_fsops.c
@@ -1571,7 +1571,7 @@ smb_fsop_write(
cr = kcr;
}
- smb_node_start_crit(snode, RW_WRITER);
+ smb_node_start_crit(snode, RW_READER);
rc = nbl_svmand(vp, kcr, &svmand);
if (rc) {
smb_node_end_crit(snode);
diff --git a/usr/src/uts/common/smbsrv/smb_ktypes.h b/usr/src/uts/common/smbsrv/smb_ktypes.h
index ba1a76b792..3bdb713337 100644
--- a/usr/src/uts/common/smbsrv/smb_ktypes.h
+++ b/usr/src/uts/common/smbsrv/smb_ktypes.h
@@ -20,7 +20,6 @@
*/
/*
* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2019 Nexenta by DDN, Inc. All rights reserved.
* Copyright 2020 RackTop Systems, Inc.
* Copyright 2020 Tintri by DDN, Inc. All rights reserved.
*/
diff --git a/usr/src/uts/i86pc/io/vmm/amd/svm.c b/usr/src/uts/i86pc/io/vmm/amd/svm.c
index 62823b3a65..0f81bcc22b 100644
--- a/usr/src/uts/i86pc/io/vmm/amd/svm.c
+++ b/usr/src/uts/i86pc/io/vmm/amd/svm.c
@@ -1912,6 +1912,19 @@ svm_dr_leave_guest(struct svm_regctx *gctx)
load_dr7(gctx->host_dr7);
}
+static void
+svm_apply_tsc_adjust(struct svm_softc *svm_sc, int vcpuid)
+{
+ const uint64_t offset = vcpu_tsc_offset(svm_sc->vm, vcpuid, true);
+ struct vmcb_ctrl *ctrl = svm_get_vmcb_ctrl(svm_sc, vcpuid);
+
+ if (ctrl->tsc_offset != offset) {
+ ctrl->tsc_offset = offset;
+ svm_set_dirty(svm_sc, vcpuid, VMCB_CACHE_I);
+ }
+}
+
+
/*
* Start vcpu with specified RIP.
*/
@@ -1971,6 +1984,8 @@ svm_vmrun(void *arg, int vcpu, uint64_t rip, pmap_t pmap)
vmm_stat_incr(vm, vcpu, VCPU_MIGRATIONS, 1);
}
+ svm_apply_tsc_adjust(svm_sc, vcpu);
+
svm_msr_guest_enter(svm_sc, vcpu);
#ifndef __FreeBSD__
diff --git a/usr/src/uts/i86pc/io/vmm/amd/svm_msr.c b/usr/src/uts/i86pc/io/vmm/amd/svm_msr.c
index f453692855..f97b61ee4e 100644
--- a/usr/src/uts/i86pc/io/vmm/amd/svm_msr.c
+++ b/usr/src/uts/i86pc/io/vmm/amd/svm_msr.c
@@ -150,15 +150,6 @@ svm_rdmsr(struct svm_softc *sc, int vcpu, uint_t num, uint64_t *result)
int error = 0;
switch (num) {
- case MSR_MCG_CAP:
- case MSR_MCG_STATUS:
- *result = 0;
- break;
- case MSR_MTRRcap:
- case MSR_MTRRdefType:
- case MSR_MTRR4kBase ... MSR_MTRR4kBase + 8:
- case MSR_MTRR16kBase ... MSR_MTRR16kBase + 1:
- case MSR_MTRR64kBase:
case MSR_SYSCFG:
case MSR_AMDK8_IPM:
case MSR_EXTFEATURES:
@@ -190,16 +181,6 @@ svm_wrmsr(struct svm_softc *sc, int vcpu, uint_t num, uint64_t val)
int error = 0;
switch (num) {
- case MSR_MCG_CAP:
- case MSR_MCG_STATUS:
- break; /* ignore writes */
- case MSR_MTRRcap:
- vm_inject_gp(sc->vm, vcpu);
- break;
- case MSR_MTRRdefType:
- case MSR_MTRR4kBase ... MSR_MTRR4kBase + 8:
- case MSR_MTRR16kBase ... MSR_MTRR16kBase + 1:
- case MSR_MTRR64kBase:
case MSR_SYSCFG:
/* Ignore writes */
break;
diff --git a/usr/src/uts/i86pc/io/vmm/intel/vmx.c b/usr/src/uts/i86pc/io/vmm/intel/vmx.c
index b5c713891c..53f19af263 100644
--- a/usr/src/uts/i86pc/io/vmm/intel/vmx.c
+++ b/usr/src/uts/i86pc/io/vmm/intel/vmx.c
@@ -1156,15 +1156,13 @@ vmx_clear_nmi_window_exiting(struct vmx *vmx, int vcpu)
static void
vmx_apply_tsc_adjust(struct vmx *vmx, int vcpu)
{
- extern hrtime_t tsc_gethrtime_tick_delta(void);
- const uint64_t target_offset = (vcpu_tsc_offset(vmx->vm, vcpu) +
- (uint64_t)tsc_gethrtime_tick_delta());
+ const uint64_t offset = vcpu_tsc_offset(vmx->vm, vcpu, true);
ASSERT(vmx->cap[vcpu].proc_ctls & PROCBASED_TSC_OFFSET);
- if (vmx->tsc_offset_active[vcpu] != target_offset) {
- vmcs_write(VMCS_TSC_OFFSET, target_offset);
- vmx->tsc_offset_active[vcpu] = target_offset;
+ if (vmx->tsc_offset_active[vcpu] != offset) {
+ vmcs_write(VMCS_TSC_OFFSET, offset);
+ vmx->tsc_offset_active[vcpu] = offset;
}
}
diff --git a/usr/src/uts/i86pc/io/vmm/intel/vmx_msr.c b/usr/src/uts/i86pc/io/vmm/intel/vmx_msr.c
index 5e404e5ebd..a7d674d005 100644
--- a/usr/src/uts/i86pc/io/vmm/intel/vmx_msr.c
+++ b/usr/src/uts/i86pc/io/vmm/intel/vmx_msr.c
@@ -410,17 +410,6 @@ vmx_rdmsr(struct vmx *vmx, int vcpuid, uint_t num, uint64_t *val)
error = 0;
switch (num) {
- case MSR_MCG_CAP:
- case MSR_MCG_STATUS:
- *val = 0;
- break;
- case MSR_MTRRcap:
- case MSR_MTRRdefType:
- case MSR_MTRR4kBase ... MSR_MTRR4kBase + 8:
- case MSR_MTRR16kBase ... MSR_MTRR16kBase + 1:
- case MSR_MTRR64kBase:
- *val = 0;
- break;
case MSR_IA32_FEATURE_CONTROL:
/*
* We currently don't support SGX support in guests, so
@@ -460,17 +449,6 @@ vmx_wrmsr(struct vmx *vmx, int vcpuid, uint_t num, uint64_t val)
error = 0;
switch (num) {
- case MSR_MCG_CAP:
- case MSR_MCG_STATUS:
- break; /* ignore writes */
- case MSR_MTRRcap:
- vm_inject_gp(vmx->vm, vcpuid);
- break;
- case MSR_MTRRdefType:
- case MSR_MTRR4kBase ... MSR_MTRR4kBase + 8:
- case MSR_MTRR16kBase ... MSR_MTRR16kBase + 1:
- case MSR_MTRR64kBase:
- break; /* Ignore writes */
case MSR_IA32_MISC_ENABLE:
changed = val ^ misc_enable;
/*
@@ -497,11 +475,6 @@ vmx_wrmsr(struct vmx *vmx, int vcpuid, uint_t num, uint64_t val)
else
vm_inject_gp(vmx->vm, vcpuid);
break;
-#ifdef __FreeBSD__
- case MSR_TSC:
- error = vmx_set_tsc_offset(vmx, vcpuid, val - rdtsc());
- break;
-#endif /* __FreeBSD__ */
default:
error = EINVAL;
break;
diff --git a/usr/src/uts/i86pc/io/vmm/sys/vmm_kernel.h b/usr/src/uts/i86pc/io/vmm/sys/vmm_kernel.h
index a7dbf84061..09e9afd8a8 100644
--- a/usr/src/uts/i86pc/io/vmm/sys/vmm_kernel.h
+++ b/usr/src/uts/i86pc/io/vmm/sys/vmm_kernel.h
@@ -236,9 +236,7 @@ enum vcpu_state vcpu_get_state(struct vm *vm, int vcpu, int *hostcpu);
void vcpu_block_run(struct vm *, int);
void vcpu_unblock_run(struct vm *, int);
-#ifndef __FreeBSD__
-uint64_t vcpu_tsc_offset(struct vm *vm, int vcpuid);
-#endif
+uint64_t vcpu_tsc_offset(struct vm *vm, int vcpuid, bool phys_adj);
static __inline int
vcpu_is_running(struct vm *vm, int vcpu, int *hostcpu)
diff --git a/usr/src/uts/i86pc/io/vmm/vmm.c b/usr/src/uts/i86pc/io/vmm/vmm.c
index 8c9a284cbf..cd235b9e4c 100644
--- a/usr/src/uts/i86pc/io/vmm/vmm.c
+++ b/usr/src/uts/i86pc/io/vmm/vmm.c
@@ -135,9 +135,7 @@ struct vcpu {
struct vm_exit exitinfo; /* (x) exit reason and collateral */
uint64_t nextrip; /* (x) next instruction to execute */
struct vie *vie_ctx; /* (x) instruction emulation context */
-#ifndef __FreeBSD__
uint64_t tsc_offset; /* (x) offset from host TSC */
-#endif
};
#define vcpu_lock_initialized(v) mtx_initialized(&((v)->mtx))
@@ -197,6 +195,7 @@ struct vm {
uint16_t cores; /* (o) num of cores/socket */
uint16_t threads; /* (o) num of threads/core */
uint16_t maxcpus; /* (o) max pluggable cpus */
+ uint64_t boot_tsc_offset; /* (i) TSC offset at VM boot */
struct ioport_config ioports; /* (o) ioport handling */
};
@@ -373,6 +372,7 @@ vcpu_init(struct vm *vm, int vcpu_id, bool create)
vcpu->guest_xcr0 = XFEATURE_ENABLED_X87;
fpu_save_area_reset(vcpu->guestfpu);
vmm_stat_init(vcpu->stats);
+ vcpu->tsc_offset = 0;
}
int
@@ -473,9 +473,6 @@ static void
vm_init(struct vm *vm, bool create)
{
int i;
-#ifndef __FreeBSD__
- uint64_t tsc_off;
-#endif
vm->cookie = VMINIT(vm, vmspace_pmap(vm->vmspace));
vm->iommu = NULL;
@@ -498,12 +495,16 @@ vm_init(struct vm *vm, bool create)
for (i = 0; i < vm->maxcpus; i++)
vcpu_init(vm, i, create);
-#ifndef __FreeBSD__
- tsc_off = (uint64_t)(-(int64_t)rdtsc());
- for (i = 0; i < vm->maxcpus; i++) {
- vm->vcpu[i].tsc_offset = tsc_off;
- }
-#endif /* __FreeBSD__ */
+ /*
+ * Configure the VM-wide TSC offset so that the call to vm_init()
+ * represents the boot time (when the TSC(s) read 0). Each vCPU will
+ * have its own offset from this, which is altered if/when the guest
+ * writes to MSR_TSC.
+ *
+ * The TSC offsetting math is all unsigned, using overflow for negative
+ * offets. A reading of the TSC is negated to form the boot offset.
+ */
+ vm->boot_tsc_offset = (uint64_t)(-(int64_t)rdtsc_offset());
}
/*
@@ -1890,23 +1891,107 @@ vm_handle_run_state(struct vm *vm, int vcpuid)
return (handled ? 0 : -1);
}
-#ifndef __FreeBSD__
+static int
+vm_handle_rdmsr(struct vm *vm, int vcpuid, struct vm_exit *vme)
+{
+ const uint32_t code = vme->u.msr.code;
+ uint64_t val = 0;
+
+ switch (code) {
+ case MSR_MCG_CAP:
+ case MSR_MCG_STATUS:
+ val = 0;
+ break;
+
+ case MSR_MTRRcap:
+ case MSR_MTRRdefType:
+ case MSR_MTRR4kBase ... MSR_MTRR4kBase + 8:
+ case MSR_MTRR16kBase ... MSR_MTRR16kBase + 1:
+ case MSR_MTRR64kBase:
+ val = 0;
+ break;
+
+ case MSR_TSC:
+ /*
+ * In all likelihood, this should always be handled in guest
+ * context by VMX/SVM rather than taking an exit. (Both VMX and
+ * SVM pass through read-only access to MSR_TSC to the guest.)
+ *
+ * No physical offset is requested of vcpu_tsc_offset() since
+ * rdtsc_offset() takes care of that instead.
+ */
+ val = vcpu_tsc_offset(vm, vcpuid, false) + rdtsc_offset();
+ break;
+
+ default:
+ /*
+ * Anything not handled at this point will be kicked out to
+ * userspace for attempted processing there.
+ */
+ return (-1);
+ }
+
+ VERIFY0(vm_set_register(vm, vcpuid, VM_REG_GUEST_RAX,
+ val & 0xffffffff));
+ VERIFY0(vm_set_register(vm, vcpuid, VM_REG_GUEST_RDX,
+ val >> 32));
+ return (0);
+}
+
static int
vm_handle_wrmsr(struct vm *vm, int vcpuid, struct vm_exit *vme)
{
- struct vcpu *cpu = &vm->vcpu[vcpuid];
+ struct vcpu *vcpu = &vm->vcpu[vcpuid];
const uint32_t code = vme->u.msr.code;
const uint64_t val = vme->u.msr.wval;
switch (code) {
+ case MSR_MCG_CAP:
+ case MSR_MCG_STATUS:
+ /* Ignore writes */
+ break;
+
+ case MSR_MTRRcap:
+ vm_inject_gp(vm, vcpuid);
+ break;
+ case MSR_MTRRdefType:
+ case MSR_MTRR4kBase ... MSR_MTRR4kBase + 8:
+ case MSR_MTRR16kBase ... MSR_MTRR16kBase + 1:
+ case MSR_MTRR64kBase:
+ /* Ignore writes */
+ break;
+
case MSR_TSC:
- cpu->tsc_offset = val - rdtsc();
- return (0);
+ /*
+ * The effect of writing the TSC MSR is that a subsequent read
+ * of the TSC would report that value written (plus any time
+ * elapsed between the write and the read). The guest TSC value
+ * is calculated from a global offset for the guest (which
+ * effectively makes its TSC read 0 at guest boot) and a
+ * per-vCPU offset to handle these writes to the MSR.
+ *
+ * To calculate that per-vCPU offset, we can work backwards from
+ * the guest value at the time of write:
+ *
+ * value = host TSC + VM boot offset + vCPU offset
+ *
+ * so therefore:
+ *
+ * value - host TSC - VM boot offset = vCPU offset
+ */
+ vcpu->tsc_offset = val - vm->boot_tsc_offset - rdtsc_offset();
+ break;
+
+ default:
+ /*
+ * Anything not handled at this point will be kicked out to
+ * userspace for attempted processing there.
+ */
+ return (-1);
}
- return (-1);
+ return (0);
}
-#endif /* __FreeBSD__ */
int
vm_suspend(struct vm *vm, enum vm_suspend_how how)
@@ -2202,7 +2287,7 @@ restart:
KASSERT(!CPU_ISSET(curcpu, &pmap->pm_active),
("vm_run: absurd pm_active"));
- tscval = rdtsc();
+ tscval = rdtsc_offset();
#ifdef __FreeBSD__
pcb = PCPU_GET(curpcb);
@@ -2240,7 +2325,7 @@ restart:
thread_affinity_clear(curthread);
#endif
- vmm_stat_incr(vm, vcpuid, VCPU_TOTAL_RUNTIME, rdtsc() - tscval);
+ vmm_stat_incr(vm, vcpuid, VCPU_TOTAL_RUNTIME, rdtsc_offset() - tscval);
critical_exit();
@@ -2282,18 +2367,17 @@ restart:
case VM_EXITCODE_VMINSN:
vm_inject_ud(vm, vcpuid);
break;
-#ifndef __FreeBSD__
+ case VM_EXITCODE_RDMSR:
+ error = vm_handle_rdmsr(vm, vcpuid, vme);
+ break;
case VM_EXITCODE_WRMSR:
- if (vm_handle_wrmsr(vm, vcpuid, vme) != 0) {
- error = -1;
- }
+ error = vm_handle_wrmsr(vm, vcpuid, vme);
break;
case VM_EXITCODE_HT: {
affinity_type = CPU_BEST;
break;
}
-#endif
case VM_EXITCODE_MTRAP:
vm_suspend_cpu(vm, vcpuid);
@@ -3097,13 +3181,21 @@ vcpu_get_state(struct vm *vm, int vcpuid, int *hostcpu)
return (state);
}
-#ifndef __FreeBSD__
uint64_t
-vcpu_tsc_offset(struct vm *vm, int vcpuid)
+vcpu_tsc_offset(struct vm *vm, int vcpuid, bool phys_adj)
{
- return (vm->vcpu[vcpuid].tsc_offset);
+ ASSERT(vcpuid >= 0 && vcpuid < vm->maxcpus);
+
+ uint64_t vcpu_off = vm->boot_tsc_offset + vm->vcpu[vcpuid].tsc_offset;
+
+ if (phys_adj) {
+ /* Include any offset for the current physical CPU too */
+ extern hrtime_t tsc_gethrtime_tick_delta(void);
+ vcpu_off += (uint64_t)tsc_gethrtime_tick_delta();
+ }
+
+ return (vcpu_off);
}
-#endif /* __FreeBSD__ */
int
vm_activate_cpu(struct vm *vm, int vcpuid)
diff --git a/usr/src/uts/i86pc/io/vmm/vmm_sol_glue.c b/usr/src/uts/i86pc/io/vmm/vmm_sol_glue.c
index 58fdc500fa..7968f461f7 100644
--- a/usr/src/uts/i86pc/io/vmm/vmm_sol_glue.c
+++ b/usr/src/uts/i86pc/io/vmm/vmm_sol_glue.c
@@ -700,3 +700,21 @@ clock_ts_to_ct(struct timespec *ts, struct clocktime *ct)
}
#endif
}
+
+/* Equivalent to the FreeBSD rdtsc(), but with any necessary per-cpu offset */
+uint64_t
+rdtsc_offset(void)
+{
+ /*
+ * The timestamp logic will decide if a delta need be applied to the
+ * unscaled hrtime reading (effectively rdtsc), but we do require it be
+ * backed by the TSC itself.
+ */
+ extern hrtime_t (*gethrtimeunscaledf)(void);
+ extern hrtime_t tsc_gethrtimeunscaled(void);
+ extern hrtime_t tsc_gethrtimeunscaled_delta(void);
+
+ ASSERT(*gethrtimeunscaledf == tsc_gethrtimeunscaled ||
+ *gethrtimeunscaledf == tsc_gethrtimeunscaled_delta);
+ return ((uint64_t)gethrtimeunscaledf());
+}
diff --git a/usr/src/uts/i86pc/io/vmm/x86.c b/usr/src/uts/i86pc/io/vmm/x86.c
index 8a52e1898e..1d3863b8a4 100644
--- a/usr/src/uts/i86pc/io/vmm/x86.c
+++ b/usr/src/uts/i86pc/io/vmm/x86.c
@@ -80,6 +80,12 @@ static uint64_t bhyve_xcpuids;
static int cpuid_leaf_b = 1;
/*
+ * Force exposition of the invariant TSC capability, regardless of whether the
+ * host CPU reports having it.
+ */
+static int vmm_force_invariant_tsc = 0;
+
+/*
* Round up to the next power of two, if necessary, and then take log2.
* Returns -1 if argument is zero.
*/
@@ -225,6 +231,7 @@ x86_emulate_cpuid(struct vm *vm, int vcpu_id, uint64_t *rax, uint64_t *rbx,
break;
case CPUID_8000_0007:
+ cpuid_count(func, param, regs);
/*
* AMD uses this leaf to advertise the processor's
* power monitoring and RAS capabilities. These
@@ -238,24 +245,26 @@ x86_emulate_cpuid(struct vm *vm, int vcpu_id, uint64_t *rax, uint64_t *rbx,
regs[0] = 0;
regs[1] = 0;
regs[2] = 0;
- regs[3] = 0;
/*
- * "Invariant TSC" can be advertised to the guest if:
- * - host TSC frequency is invariant
- * - host TSCs are synchronized across physical cpus
+ * If the host system possesses an invariant TSC, then
+ * it is safe to expose to the guest.
*
- * XXX This still falls short because the vcpu
- * can observe the TSC moving backwards as it
- * migrates across physical cpus. But at least
- * it should discourage the guest from using the
- * TSC to keep track of time.
+ * If there is measured skew between host TSCs, it will
+ * be properly offset so guests do not observe any
+ * change between CPU migrations.
*/
-#ifdef __FreeBSD__
- /* XXXJOY: Wire up with our own TSC logic */
- if (tsc_is_invariant && smp_tsc)
+ regs[3] &= AMDPM_TSC_INVARIANT;
+
+ /*
+ * Since illumos avoids deep C-states on CPUs which do
+ * not support an invariant TSC, it may be safe (and
+ * desired) to unconditionally expose that capability to
+ * the guest.
+ */
+ if (vmm_force_invariant_tsc != 0) {
regs[3] |= AMDPM_TSC_INVARIANT;
-#endif /* __FreeBSD__ */
+ }
break;
case CPUID_8000_001D: