Merge ^/head r357368 through r357388.

This commit is contained in:
Dimitry Andric 2020-02-01 22:07:37 +00:00
commit 8be7eb94e8
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/projects/clang1000-import/; revision=357390
27 changed files with 528 additions and 308 deletions

View File

@ -73,7 +73,11 @@ typedef struct {
#define EXIT_FAILURE 1
#define EXIT_SUCCESS 0
#define RAND_MAX 0x7ffffffd
/*
* I.e., INT_MAX; rand(3) returns a signed integer but must produce output in
* the range [0, RAND_MAX], so half of the possible output range is unused.
*/
#define RAND_MAX 0x7fffffff
__BEGIN_DECLS
#ifdef _XLOCALE_H_

View File

@ -54,8 +54,6 @@ FBSD_1.0 {
radixsort;
sradixsort;
rand_r;
rand;
srand;
srandom;
srandomdev;
initstate;
@ -125,6 +123,8 @@ FBSD_1.5 {
FBSD_1.6 {
qsort_s;
rand;
srand;
};
FBSDprivate_1.0 {

View File

@ -32,7 +32,7 @@
.\" @(#)rand.3 8.1 (Berkeley) 6/4/93
.\" $FreeBSD$
.\"
.Dd December 14, 2019
.Dd February 1, 2020
.Dt RAND 3
.Os
.Sh NAME
@ -59,49 +59,52 @@ Applications which require unpredictable random numbers should use
instead.
.Ef
.Pp
These interfaces are obsoleted by
.Xr random 3 .
.Pp
The
.Fn rand
function computes a sequence of pseudo-random integers in the range
of 0 to
.Dv RAND_MAX
(as defined by the header file
.In stdlib.h ) .
.Dv RAND_MAX ,
inclusive.
.Pp
The
.Fn srand
function sets its argument
function seeds the algorithm with the
.Fa seed
as the seed for a new sequence of
pseudo-random numbers to be returned by
.Fn rand .
These sequences are repeatable by calling
parameter.
Repeatable sequences of
.Fn rand
output may be obtained by calling
.Fn srand
with the same seed value.
with the same
.Fa seed .
.Fn rand
is implicitly initialized as if
.Fn srand "1"
had been invoked explicitly.
.Pp
If no
.Fa seed
value is provided, the functions are automatically
seeded with a value of 1.
.Pp
The
In
.Fx 13 ,
.Fn rand
is implemented using the same 128-byte state LFSR generator algorithm as
.Xr random 3 .
However, the legacy
.Fn rand_r
function
provides the same functionality as
.Fn rand .
A pointer to the context value
.Fa ctx
must be supplied by the caller.
.Pp
For better generator quality, use
.Xr random 3
or
.Xr lrand48 3 .
function is not (and can not be, because of its limited
.Fa *ctx
size).
.Fn rand_r
implements the historical, poor-quality Park-Miller 32-bit LCG and should not
be used in new designs.
.Sh IMPLEMENTATION NOTES
Since
.Fx 13 ,
.Fn rand
is implemented with the same generator as
.Xr random 3 ,
so the low-order bits should no longer be significantly worse than the
high-order bits.
.Sh SEE ALSO
.Xr arc4random 3 ,
.Xr lrand48 3 ,
.Xr random 3 ,
.Xr random 4
.Sh STANDARDS
@ -115,5 +118,32 @@ conform to
.Pp
The
.Fn rand_r
function is marked as obsolescent in POSIX and may be removed in a future
revision of the standard.
function is not part of
.St -isoC
and is marked obsolescent in
.St -p1003.1-2008 .
It may be removed in a future revision of POSIX.
.Sh CAVEATS
Prior to
.Fx 13 ,
.Fn rand
used the historical Park-Miller generator with 32 bits of state and produced
poor quality output, especially in the lower bits.
.Fn rand
in earlier versions of
.Fx ,
as well as other standards-conforming implementations, may continue to produce
poor quality output.
.Pp
.Em These functions should not be used in portable applications that want a
.Em high quality or high performance pseudorandom number generator .
One possible replacement,
.Xr random 3 ,
is portable to Linux — but it is not especially fast, nor standardized.
.Pp
If broader portability or better performance is desired, any of the widely
available and permissively licensed SFC64/32, JSF64/32, PCG64/32, or SplitMix64
algorithm implementations may be embedded in your application.
These algorithms have the benefit of requiring less space than
.Xr random 3
and being quite fast (in header inline implementations).

View File

@ -40,11 +40,60 @@ __FBSDID("$FreeBSD$");
#include "namespace.h"
#include <sys/param.h>
#include <sys/sysctl.h>
#include <assert.h>
#include <stdbool.h>
#include <stdlib.h>
#include <syslog.h>
#include "un-namespace.h"
#include "random.h"
/*
* Implement rand(3), the standard C PRNG API, using the non-standard but
* higher quality random(3) implementation and the same size 128-byte state
* LFSR as the random(3) default.
*
* It turns out there are portable applications that want a PRNG but are too
* lazy to use better-but-nonstandard interfaces like random(3), when
* available, and too lazy to import higher-quality and faster PRNGs into their
* codebase (such as any of SFC, JSF, 128-bit LCGs, PCG, or Splitmix64).
*
* Since we're stuck with rand(3) due to the C standard, we can at least have
* it produce a relatively good PRNG sequence using our existing random(3)
* LFSR. The random(3) design is not particularly fast nor compact, but it has
* the advantage of being the one already in the tree.
*/
static struct __random_state *rand3_state;
static void
initialize_rand3(void)
{
int error;
rand3_state = allocatestate(TYPE_3);
error = initstate_r(rand3_state, 1, rand3_state->rst_randtbl, BREAK_3);
assert(error == 0);
}
int
rand(void)
{
if (rand3_state == NULL)
initialize_rand3();
return ((int)random_r(rand3_state));
}
void
srand(unsigned seed)
{
if (rand3_state == NULL)
initialize_rand3();
srandom_r(rand3_state, seed);
}
/*
* FreeBSD 12 and prior compatibility implementation of rand(3).
*/
static int
do_rand(unsigned long *ctx)
{
@ -71,7 +120,9 @@ do_rand(unsigned long *ctx)
return (x);
}
/*
* Can't fix this garbage; too little state.
*/
int
rand_r(unsigned *ctx)
{
@ -84,21 +135,23 @@ rand_r(unsigned *ctx)
return (r);
}
static u_long next = 1;
int __rand_fbsd12(void);
int
rand(void)
__rand_fbsd12(void)
{
return (do_rand(&next));
}
__sym_compat(rand, __rand_fbsd12, FBSD_1.0);
void __srand_fbsd12(unsigned seed);
void
srand(unsigned seed)
__srand_fbsd12(unsigned seed)
{
next = seed;
}
__sym_compat(srand, __srand_fbsd12, FBSD_1.0);
void __sranddev_fbsd12(void);
void

View File

@ -28,7 +28,7 @@
.\" @(#)random.3 8.1 (Berkeley) 6/4/93
.\" $FreeBSD$
.\"
.Dd January 20, 2020
.Dd February 1, 2020
.Dt RANDOM 3
.Os
.Sh NAME
@ -74,8 +74,7 @@ The period of this random number generator is very large, approximately
.Pp
If initialized with less than 32 bytes of state,
.Fn random
uses the same poor-quality Park-Miller LCG as
.Xr rand 3 .
uses the poor-quality 32-bit Park-Miller LCG.
.Pp
The
.Fn random
@ -85,9 +84,6 @@ functions are analagous to
.Xr rand 3
and
.Xr srand 3 .
The difference is that
.Xr rand 3
is a worse pseudo-random number generator.
.Pp
Like
.Xr rand 3 ,

View File

@ -104,48 +104,13 @@ __FBSDID("$FreeBSD$");
* byte buffer it is about 5 percent faster.
*/
/*
* For each of the currently supported random number generators, we have a
* break value on the amount of state information (you need at least this
* many bytes of state info to support this random number generator), a degree
* for the polynomial (actually a trinomial) that the R.N.G. is based on, and
* the separation between the two lower order coefficients of the trinomial.
*/
#define TYPE_0 0 /* linear congruential */
#define BREAK_0 8
#define DEG_0 0
#define SEP_0 0
#define TYPE_1 1 /* x**7 + x**3 + 1 */
#define BREAK_1 32
#define DEG_1 7
#define SEP_1 3
#define TYPE_2 2 /* x**15 + x + 1 */
#define BREAK_2 64
#define DEG_2 15
#define SEP_2 1
#define TYPE_3 3 /* x**31 + x**3 + 1 */
#define BREAK_3 128
#define DEG_3 31
#define SEP_3 3
#define TYPE_4 4 /* x**63 + x + 1 */
#define BREAK_4 256
#define DEG_4 63
#define SEP_4 1
/*
* Array versions of the above information to make code run faster --
* relies on fact that TYPE_i == i.
*/
#define MAX_TYPES 5 /* max number of types above */
#define NSHUFF 50 /* to drop some "seed -> 1st value" linearity */
static const int degrees[MAX_TYPES] = { DEG_0, DEG_1, DEG_2, DEG_3, DEG_4 };
static const int seps [MAX_TYPES] = { SEP_0, SEP_1, SEP_2, SEP_3, SEP_4 };
static const int seps[MAX_TYPES] = { SEP_0, SEP_1, SEP_2, SEP_3, SEP_4 };
static const int breaks[MAX_TYPES] = {
BREAK_0, BREAK_1, BREAK_2, BREAK_3, BREAK_4
};
/*
* Initially, everything is set up as if from:
@ -524,3 +489,19 @@ random(void)
{
return (random_r(&implicit));
}
struct __random_state *
allocatestate(unsigned type)
{
size_t asize;
/* No point using this interface to get the Park-Miller LCG. */
if (type < TYPE_1)
abort();
/* Clamp to widest supported variant. */
if (type > (MAX_TYPES - 1))
type = (MAX_TYPES - 1);
asize = sizeof(struct __random_state) + (size_t)breaks[type];
return (malloc(asize));
}

View File

@ -27,6 +27,44 @@
#pragma once
/*
* For each of the currently supported random number generators, we have a
* break value on the amount of state information (you need at least this
* many bytes of state info to support this random number generator), a degree
* for the polynomial (actually a trinomial) that the R.N.G. is based on, and
* the separation between the two lower order coefficients of the trinomial.
*/
#define TYPE_0 0 /* linear congruential */
#define BREAK_0 8
#define DEG_0 0
#define SEP_0 0
#define TYPE_1 1 /* x**7 + x**3 + 1 */
#define BREAK_1 32
#define DEG_1 7
#define SEP_1 3
#define TYPE_2 2 /* x**15 + x + 1 */
#define BREAK_2 64
#define DEG_2 15
#define SEP_2 1
#define TYPE_3 3 /* x**31 + x**3 + 1 */
#define BREAK_3 128
#define DEG_3 31
#define SEP_3 3
#define TYPE_4 4 /* x**63 + x + 1 */
#define BREAK_4 256
#define DEG_4 63
#define SEP_4 1
/*
* Array versions of the above information to make code run faster --
* relies on fact that TYPE_i == i.
*/
#define MAX_TYPES 5 /* max number of types above */
/* A full instance of the random(3) generator. */
struct __random_state {
uint32_t *rst_fptr;
@ -40,6 +78,7 @@ struct __random_state {
uint32_t rst_randtbl[];
};
struct __random_state *allocatestate(unsigned type);
int initstate_r(struct __random_state *, unsigned, uint32_t *, size_t);
long random_r(struct __random_state *);
void srandom_r(struct __random_state *, unsigned);

View File

@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd January 22, 2020
.Dd February 1, 2020
.Dt HWPSTATE_INTEL 4
.Os
.Sh NAME
@ -49,7 +49,15 @@ Can be used to disable
.Nm ,
allowing other compatible drivers to manage performance states, like
.Xr est 4 .
.Pq default 0
Defaults to
.Dv Qq 0
(enabled).
.It Va machdep.hwpstate_pkg_ctrl
Selects between package-level control (the default) and per-core control.
.Dv Qq 1
selects package-level control and
.Dv Qq 0
selects core-level control.
.El
.Sh SYSCTL VARIABLES
The following

View File

@ -42,7 +42,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/syscallsubr.h>
#include <sys/vnode.h>
#include <sys/proc.h>
#include <sys/malloc.h>
@ -60,28 +60,25 @@ __FBSDID("$FreeBSD$");
* Find pathname of process's current directory.
*/
int
linux_getcwd(struct thread *td, struct linux_getcwd_args *args)
linux_getcwd(struct thread *td, struct linux_getcwd_args *uap)
{
char *path;
int error, lenused;
char *buf, *retbuf;
size_t buflen;
int error;
/*
* Linux returns ERANGE instead of EINVAL.
*/
if (args->bufsize < 2)
buflen = uap->bufsize;
if (__predict_false(buflen < 2))
return (ERANGE);
if (buflen > LINUX_PATH_MAX)
buflen = LINUX_PATH_MAX;
path = malloc(LINUX_PATH_MAX, M_LINUX, M_WAITOK);
error = kern___getcwd(td, path, UIO_SYSSPACE, args->bufsize,
LINUX_PATH_MAX);
buf = malloc(buflen, M_TEMP, M_WAITOK);
error = vn_getcwd(td, buf, &retbuf, &buflen);
if (error == 0) {
lenused = strlen(path) + 1;
error = copyout(path, args->buf, lenused);
error = copyout(retbuf, uap->buf, buflen);
if (error == 0)
td->td_retval[0] = lenused;
td->td_retval[0] = buflen;
}
free(path, M_LINUX);
free(buf, M_TEMP);
return (error);
}

View File

@ -70,7 +70,8 @@ __FBSDID("$FreeBSD$");
#define TPM_CRB_CTRL_STS_ERR_BIT BIT(0)
#define TPM_CRB_CTRL_STS_IDLE_BIT BIT(1)
#define TPM_CRB_CTRL_CANCEL_CMD BIT(0)
#define TPM_CRB_CTRL_CANCEL_CMD 0x1
#define TPM_CRB_CTRL_CANCEL_CLEAR 0x0
#define TPM_CRB_CTRL_START_CMD BIT(0)
@ -298,7 +299,7 @@ tpmcrb_cancel_cmd(struct tpm_sc *sc)
return (false);
}
WR4(sc, TPM_CRB_CTRL_CANCEL, ~TPM_CRB_CTRL_CANCEL_CMD);
WR4(sc, TPM_CRB_CTRL_CANCEL, TPM_CRB_CTRL_CANCEL_CLEAR;
return (true);
}
@ -330,7 +331,7 @@ tpmcrb_transmit(struct tpm_sc *sc, size_t length)
return (EIO);
}
/* Clear cancellation bit */
WR4(sc, TPM_CRB_CTRL_CANCEL, ~TPM_CRB_CTRL_CANCEL_CMD);
WR4(sc, TPM_CRB_CTRL_CANCEL, TPM_CRB_CTRL_CANCEL_CLEAR;
/* Switch device to idle state if necessary */
if (!(RD4(sc, TPM_CRB_CTRL_STS) & TPM_CRB_CTRL_STS_IDLE_BIT)) {

View File

@ -386,12 +386,11 @@ tpmtis_go_ready(struct tpm_sc *sc)
mask = TPM_STS_CMD_RDY;
sc->intr_type = TPM_INT_STS_CMD_RDY;
OR4(sc, TPM_STS, TPM_STS_CMD_RDY);
WR4(sc, TPM_STS, TPM_STS_CMD_RDY);
bus_barrier(sc->mem_res, TPM_STS, 4, BUS_SPACE_BARRIER_WRITE);
if (!tpm_wait_for_u32(sc, TPM_STS, mask, mask, TPM_TIMEOUT_B))
return (false);
AND4(sc, TPM_STS, ~TPM_STS_CMD_RDY);
return (true);
}

View File

@ -274,7 +274,7 @@ devfs_vptocnp(struct vop_vptocnp_args *ap)
struct vnode **dvp = ap->a_vpp;
struct devfs_mount *dmp;
char *buf = ap->a_buf;
int *buflen = ap->a_buflen;
size_t *buflen = ap->a_buflen;
struct devfs_dirent *dd, *de;
int i, error;

View File

@ -377,7 +377,7 @@ pfs_vptocnp(struct vop_vptocnp_args *ap)
struct pfs_node *pn;
struct mount *mp;
char *buf = ap->a_buf;
int *buflen = ap->a_buflen;
size_t *buflen = ap->a_buflen;
char pidbuf[PFS_NAMELEN];
pid_t pid = pvd->pvd_pid;
int len, i, error, locked;

View File

@ -1491,7 +1491,7 @@ tmpfs_vptocnp_dir(struct tmpfs_node *tn, struct tmpfs_node *tnp,
static int
tmpfs_vptocnp_fill(struct vnode *vp, struct tmpfs_node *tn,
struct tmpfs_node *tnp, char *buf, int *buflen, struct vnode **dvp)
struct tmpfs_node *tnp, char *buf, size_t *buflen, struct vnode **dvp)
{
struct tmpfs_dirent *de;
int error, i;
@ -1531,7 +1531,7 @@ tmpfs_vptocnp(struct vop_vptocnp_args *ap)
struct tmpfs_dirent *de;
struct tmpfs_mount *tm;
char *buf;
int *buflen;
size_t *buflen;
int error;
vp = ap->a_vp;

View File

@ -3608,6 +3608,7 @@ coredump(struct thread *td)
struct vnode *vp;
struct flock lf;
struct vattr vattr;
size_t fullpathsize;
int error, error1, locked;
char *name; /* name of corefile */
void *rl_cookie;
@ -3711,13 +3712,14 @@ coredump(struct thread *td)
* if the path of the core is relative, add the current dir in front if it.
*/
if (name[0] != '/') {
fullpath = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
if (kern___getcwd(td, fullpath, UIO_SYSSPACE, MAXPATHLEN, MAXPATHLEN) != 0) {
free(fullpath, M_TEMP);
fullpathsize = MAXPATHLEN;
freepath = malloc(fullpathsize, M_TEMP, M_WAITOK);
if (vn_getcwd(td, freepath, &fullpath, &fullpathsize) != 0) {
free(freepath, M_TEMP);
goto out2;
}
devctl_safe_quote_sb(sb, fullpath);
free(fullpath, M_TEMP);
free(freepath, M_TEMP);
sbuf_putc(sb, '/');
}
devctl_safe_quote_sb(sb, name);

View File

@ -364,7 +364,7 @@ STATNODE_COUNTER(numposhits, "Number of cache hits (positive)");
STATNODE_COUNTER(numnegzaps,
"Number of cache hits (negative) we do not want to cache");
STATNODE_COUNTER(numneghits, "Number of cache hits (negative)");
/* These count for kern___getcwd(), too. */
/* These count for vn_getcwd(), too. */
STATNODE_COUNTER(numfullpathcalls, "Number of fullpath search calls");
STATNODE_COUNTER(numfullpathfail1, "Number of fullpath search errors (ENOTDIR)");
STATNODE_COUNTER(numfullpathfail2,
@ -388,7 +388,7 @@ STATNODE_COUNTER(shrinking_skipped,
static void cache_zap_locked(struct namecache *ncp, bool neg_locked);
static int vn_fullpath1(struct thread *td, struct vnode *vp, struct vnode *rdir,
char *buf, char **retbuf, u_int buflen);
char *buf, char **retbuf, size_t *buflen);
static MALLOC_DEFINE(M_VFSCACHE, "vfscache", "VFS name cache entries");
@ -2167,39 +2167,35 @@ vfs_cache_lookup(struct vop_lookup_args *ap)
return (error);
}
/*
* XXX All of these sysctls would probably be more productive dead.
*/
static int __read_mostly disablecwd;
SYSCTL_INT(_debug, OID_AUTO, disablecwd, CTLFLAG_RW, &disablecwd, 0,
"Disable the getcwd syscall");
/* Implementation of the getcwd syscall. */
int
sys___getcwd(struct thread *td, struct __getcwd_args *uap)
{
char *buf, *retbuf;
size_t buflen;
int error;
return (kern___getcwd(td, uap->buf, UIO_USERSPACE, uap->buflen,
MAXPATHLEN));
buflen = uap->buflen;
if (__predict_false(buflen < 2))
return (EINVAL);
if (buflen > MAXPATHLEN)
buflen = MAXPATHLEN;
buf = malloc(buflen, M_TEMP, M_WAITOK);
error = vn_getcwd(td, buf, &retbuf, &buflen);
if (error == 0)
error = copyout(retbuf, uap->buf, buflen);
free(buf, M_TEMP);
return (error);
}
int
kern___getcwd(struct thread *td, char *buf, enum uio_seg bufseg, size_t buflen,
size_t path_max)
vn_getcwd(struct thread *td, char *buf, char **retbuf, size_t *buflen)
{
char *bp, *tmpbuf;
struct filedesc *fdp;
struct vnode *cdir, *rdir;
int error;
if (__predict_false(disablecwd))
return (ENODEV);
if (__predict_false(buflen < 2))
return (EINVAL);
if (buflen > path_max)
buflen = path_max;
tmpbuf = malloc(buflen, M_TEMP, M_WAITOK);
fdp = td->td_proc->p_fd;
FILEDESC_SLOCK(fdp);
cdir = fdp->fd_cdir;
@ -2207,32 +2203,17 @@ kern___getcwd(struct thread *td, char *buf, enum uio_seg bufseg, size_t buflen,
rdir = fdp->fd_rdir;
vrefact(rdir);
FILEDESC_SUNLOCK(fdp);
error = vn_fullpath1(td, cdir, rdir, tmpbuf, &bp, buflen);
error = vn_fullpath1(td, cdir, rdir, buf, retbuf, buflen);
vrele(rdir);
vrele(cdir);
if (!error) {
if (bufseg == UIO_SYSSPACE)
bcopy(bp, buf, strlen(bp) + 1);
else
error = copyout(bp, buf, strlen(bp) + 1);
#ifdef KTRACE
if (KTRPOINT(curthread, KTR_NAMEI))
ktrnamei(bp);
if (KTRPOINT(curthread, KTR_NAMEI) && error == 0)
ktrnamei(*retbuf);
#endif
}
free(tmpbuf, M_TEMP);
return (error);
}
/*
* Thus begins the fullpath magic.
*/
static int __read_mostly disablefullpath;
SYSCTL_INT(_debug, OID_AUTO, disablefullpath, CTLFLAG_RW, &disablefullpath, 0,
"Disable the vn_fullpath function");
/*
* Retrieve the full filesystem path that correspond to a vnode from the name
* cache (if available)
@ -2243,20 +2224,20 @@ vn_fullpath(struct thread *td, struct vnode *vn, char **retbuf, char **freebuf)
char *buf;
struct filedesc *fdp;
struct vnode *rdir;
size_t buflen;
int error;
if (__predict_false(disablefullpath))
return (ENODEV);
if (__predict_false(vn == NULL))
return (EINVAL);
buf = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
buflen = MAXPATHLEN;
buf = malloc(buflen, M_TEMP, M_WAITOK);
fdp = td->td_proc->p_fd;
FILEDESC_SLOCK(fdp);
rdir = fdp->fd_rdir;
vrefact(rdir);
FILEDESC_SUNLOCK(fdp);
error = vn_fullpath1(td, vn, rdir, buf, retbuf, MAXPATHLEN);
error = vn_fullpath1(td, vn, rdir, buf, retbuf, &buflen);
vrele(rdir);
if (!error)
@ -2277,14 +2258,14 @@ vn_fullpath_global(struct thread *td, struct vnode *vn,
char **retbuf, char **freebuf)
{
char *buf;
size_t buflen;
int error;
if (__predict_false(disablefullpath))
return (ENODEV);
if (__predict_false(vn == NULL))
return (EINVAL);
buf = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
error = vn_fullpath1(td, vn, rootvnode, buf, retbuf, MAXPATHLEN);
buflen = MAXPATHLEN;
buf = malloc(buflen, M_TEMP, M_WAITOK);
error = vn_fullpath1(td, vn, rootvnode, buf, retbuf, &buflen);
if (!error)
*freebuf = buf;
else
@ -2293,7 +2274,7 @@ vn_fullpath_global(struct thread *td, struct vnode *vn,
}
int
vn_vptocnp(struct vnode **vp, struct ucred *cred, char *buf, u_int *buflen)
vn_vptocnp(struct vnode **vp, struct ucred *cred, char *buf, size_t *buflen)
{
struct vnode *dvp;
struct namecache *ncp;
@ -2355,17 +2336,20 @@ vn_vptocnp(struct vnode **vp, struct ucred *cred, char *buf, u_int *buflen)
}
/*
* The magic behind kern___getcwd() and vn_fullpath().
* The magic behind vn_getcwd() and vn_fullpath().
*/
static int
vn_fullpath1(struct thread *td, struct vnode *vp, struct vnode *rdir,
char *buf, char **retbuf, u_int buflen)
char *buf, char **retbuf, size_t *len)
{
int error, slash_prefixed;
#ifdef KDTRACE_HOOKS
struct vnode *startvp = vp;
#endif
struct vnode *vp1;
size_t buflen;
buflen = *len;
buflen--;
buf[buflen] = '\0';
@ -2457,6 +2441,7 @@ vn_fullpath1(struct thread *td, struct vnode *vp, struct vnode *rdir,
SDT_PROBE3(vfs, namecache, fullpath, return, 0, startvp, buf + buflen);
*retbuf = buf + buflen;
*len -= buflen;
return (0);
}
@ -2515,9 +2500,6 @@ vn_commname(struct vnode *vp, char *buf, u_int buflen)
* Requires a locked, referenced vnode.
* Vnode is re-locked on success or ENODEV, otherwise unlocked.
*
* If sysctl debug.disablefullpath is set, ENODEV is returned,
* vnode is left locked and path remain untouched.
*
* If vp is a directory, the call to vn_fullpath_global() always succeeds
* because it falls back to the ".." lookup if the namecache lookup fails.
*/
@ -2532,10 +2514,6 @@ vn_path_to_global_path(struct thread *td, struct vnode *vp, char *path,
ASSERT_VOP_ELOCKED(vp, __func__);
/* Return ENODEV if sysctl debug.disablefullpath==1 */
if (__predict_false(disablefullpath))
return (ENODEV);
/* Construct global filesystem path from vp. */
VOP_UNLOCK(vp);
error = vn_fullpath_global(td, vp, &rpath, &fbuf);

View File

@ -804,7 +804,7 @@ vop_stdvptocnp(struct vop_vptocnp_args *ap)
struct vnode **dvp = ap->a_vpp;
struct ucred *cred = ap->a_cred;
char *buf = ap->a_buf;
int *buflen = ap->a_buflen;
size_t *buflen = ap->a_buflen;
char *dirbuf, *cpos;
int i, error, eofflag, dirbuflen, flags, locked, len, covered;
off_t off;

View File

@ -640,7 +640,7 @@ vop_vptocnp {
OUT struct vnode **vpp;
IN struct ucred *cred;
INOUT char *buf;
INOUT int *buflen;
INOUT size_t *buflen;
};

View File

@ -45,11 +45,21 @@ __FBSDID("$FreeBSD$");
#include <machine/cpu.h>
#include <dev/extres/clk/clk.h>
#include <dev/extres/clk/clk_fixed.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
#include <dev/ofw/openfirm.h>
#include <gnu/dts/include/dt-bindings/clock/sifive-fu540-prci.h>
static struct ofw_compat_data compat_data[] = {
{ "sifive,aloeprci0", 1 },
{ "sifive,ux00prci0", 1 },
{ "sifive,fu540-c000-prci", 1 },
{ NULL, 0 },
};
static struct resource_spec prci_spec[] = {
{ SYS_RES_MEMORY, 0, RF_ACTIVE },
RESOURCE_SPEC_END
@ -68,6 +78,7 @@ struct prci_softc {
struct prci_clk_pll_sc {
struct prci_softc *parent_sc;
uint32_t reg;
};
#define PRCI_LOCK(sc) mtx_lock(&(sc)->mtx)
@ -75,17 +86,51 @@ struct prci_clk_pll_sc {
#define PRCI_ASSERT_LOCKED(sc) mtx_assert(&(sc)->mtx, MA_OWNED);
#define PRCI_ASSERT_UNLOCKED(sc) mtx_assert(&(sc)->mtx, MA_NOTOWNED);
#define PRCI_COREPLL 0x4
#define PRCI_COREPLL_DIVR_MASK 0x3f
#define PRCI_COREPLL_DIVR_SHIFT 0
#define PRCI_COREPLL_DIVF_MASK 0x7fc0
#define PRCI_COREPLL_DIVF_SHIFT 6
#define PRCI_COREPLL_DIVQ_MASK 0x38000
#define PRCI_COREPLL_DIVQ_SHIFT 15
#define PRCI_COREPLL_CFG0 0x4
#define PRCI_DDRPLL_CFG0 0xC
#define PRCI_GEMGXLPLL_CFG0 0x1C
#define PRCI_PLL_DIVR_MASK 0x3f
#define PRCI_PLL_DIVR_SHIFT 0
#define PRCI_PLL_DIVF_MASK 0x7fc0
#define PRCI_PLL_DIVF_SHIFT 6
#define PRCI_PLL_DIVQ_MASK 0x38000
#define PRCI_PLL_DIVQ_SHIFT 15
#define PRCI_READ(_sc, _reg) \
bus_space_read_4((_sc)->bst, (_sc)->bsh, (_reg))
struct prci_pll_def {
uint32_t id;
const char *name;
uint32_t reg;
};
#define PLL(_id, _name, _base) \
{ \
.id = (_id), \
.name = (_name), \
.reg = (_base), \
}
/* PLL Clocks */
struct prci_pll_def pll_clks[] = {
PLL(PRCI_CLK_COREPLL, "coreclk", PRCI_COREPLL_CFG0),
PLL(PRCI_CLK_DDRPLL, "ddrclk", PRCI_DDRPLL_CFG0),
PLL(PRCI_CLK_GEMGXLPLL, "gemgxclk", PRCI_GEMGXLPLL_CFG0),
};
/* Fixed divisor clock TLCLK. */
struct clk_fixed_def tlclk_def = {
.clkdef.id = PRCI_CLK_TLCLK,
.clkdef.name = "prci_tlclk",
.clkdef.parent_names = (const char *[]){"coreclk"},
.clkdef.parent_cnt = 1,
.clkdef.flags = CLK_NODE_STATIC_STRINGS,
.mult = 1,
.div = 2,
};
static int
prci_clk_pll_init(struct clknode *clk, device_t dev)
{
@ -121,11 +166,11 @@ prci_clk_pll_recalc(struct clknode *clk, uint64_t *freq)
}
/* Calculate the PLL output */
val = PRCI_READ(sc->parent_sc, PRCI_COREPLL);
val = PRCI_READ(sc->parent_sc, sc->reg);
divf = (val & PRCI_COREPLL_DIVF_MASK) >> PRCI_COREPLL_DIVF_SHIFT;
divq = (val & PRCI_COREPLL_DIVQ_MASK) >> PRCI_COREPLL_DIVQ_SHIFT;
divr = (val & PRCI_COREPLL_DIVR_MASK) >> PRCI_COREPLL_DIVR_SHIFT;
divf = (val & PRCI_PLL_DIVF_MASK) >> PRCI_PLL_DIVF_SHIFT;
divq = (val & PRCI_PLL_DIVQ_MASK) >> PRCI_PLL_DIVQ_SHIFT;
divr = (val & PRCI_PLL_DIVR_MASK) >> PRCI_PLL_DIVR_SHIFT;
*freq = refclk / (divr + 1) * (2 * (divf + 1)) / (1 << divq);
@ -151,7 +196,7 @@ prci_probe(device_t dev)
if (!ofw_bus_status_okay(dev))
return (ENXIO);
if (!ofw_bus_is_compatible(dev, "sifive,aloeprci0"))
if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
return (ENXIO);
device_set_desc(dev, "SiFive FU540 Power Reset Clocking Interrupt");
@ -160,7 +205,8 @@ prci_probe(device_t dev)
}
static void
prci_pll_register(struct prci_softc *parent_sc, struct clknode_init_def *clkdef)
prci_pll_register(struct prci_softc *parent_sc, struct clknode_init_def *clkdef,
uint32_t reg)
{
struct clknode *clk;
struct prci_clk_pll_sc *sc;
@ -172,6 +218,7 @@ prci_pll_register(struct prci_softc *parent_sc, struct clknode_init_def *clkdef)
sc = clknode_get_softc(clk);
sc->parent_sc = parent_sc;
sc->reg = reg;
clknode_register(parent_sc->clkdom, clk);
}
@ -201,14 +248,12 @@ prci_attach(device_t dev)
node = ofw_bus_get_node(dev);
error = ofw_bus_parse_xref_list_get_length(node, "clocks",
"#clock-cells", &ncells);
if (error != 0 || ncells != 1) {
if (error != 0 || ncells < 1) {
device_printf(dev, "couldn't find parent clock\n");
goto fail;
}
bzero(&clkdef, sizeof(clkdef));
clkdef.id = 0;
clkdef.name = "coreclk";
clkdef.parent_names = mallocarray(ncells, sizeof(char *), M_OFWPROP,
M_WAITOK);
for (i = 0; i < ncells; i++) {
@ -232,7 +277,21 @@ prci_attach(device_t dev)
}
/* We can't free a clkdom, so from now on we cannot fail. */
prci_pll_register(sc, &clkdef);
for (i = 0; i < nitems(pll_clks); i++) {
clkdef.id = pll_clks[i].id;
clkdef.name = pll_clks[i].name;
prci_pll_register(sc, &clkdef, pll_clks[i].reg);
}
/*
* Register the fixed clock "tlclk".
*
* If an older device tree is being used, tlclk may appear as its own
* entity in the device tree, under soc/tlclk. If this is the case it
* will be registered automatically by the fixed_clk driver, and the
* version we register here will be an unreferenced duplicate.
*/
clknode_fixed_register(sc->clkdom, &tlclk_def);
error = clkdom_finit(sc->clkdom);
if (error)

View File

@ -65,8 +65,6 @@ struct uio;
typedef int (*mmap_check_fp_fn)(struct file *, int, int, int);
int kern___getcwd(struct thread *td, char *buf, enum uio_seg bufseg,
size_t buflen, size_t path_max);
int kern_accept(struct thread *td, int s, struct sockaddr **name,
socklen_t *namelen, struct file **fp);
int kern_accept4(struct thread *td, int s, struct sockaddr **name,

View File

@ -631,7 +631,8 @@ int insmntque(struct vnode *vp, struct mount *mp);
u_quad_t init_va_filerev(void);
int speedup_syncer(void);
int vn_vptocnp(struct vnode **vp, struct ucred *cred, char *buf,
u_int *buflen);
size_t *buflen);
int vn_getcwd(struct thread *td, char *buf, char **retbuf, size_t *buflen);
int vn_fullpath(struct thread *td, struct vnode *vn,
char **retbuf, char **freebuf);
int vn_fullpath_global(struct thread *td, struct vnode *vn,

View File

@ -1155,23 +1155,6 @@ vm_page_xunbusy_hard_unchecked(vm_page_t m)
vm_page_xunbusy_hard_tail(m);
}
/*
* Avoid releasing and reacquiring the same page lock.
*/
void
vm_page_change_lock(vm_page_t m, struct mtx **mtx)
{
struct mtx *mtx1;
mtx1 = vm_page_lockptr(m);
if (*mtx == mtx1)
return;
if (*mtx != NULL)
mtx_unlock(*mtx);
*mtx = mtx1;
mtx_lock(mtx1);
}
/*
* vm_page_unhold_pages:
*
@ -2444,7 +2427,6 @@ vm_page_t
vm_page_scan_contig(u_long npages, vm_page_t m_start, vm_page_t m_end,
u_long alignment, vm_paddr_t boundary, int options)
{
struct mtx *m_mtx;
vm_object_t object;
vm_paddr_t pa;
vm_page_t m, m_run;
@ -2458,7 +2440,6 @@ vm_page_scan_contig(u_long npages, vm_page_t m_start, vm_page_t m_end,
KASSERT(powerof2(boundary), ("boundary is not a power of 2"));
m_run = NULL;
run_len = 0;
m_mtx = NULL;
for (m = m_start; m < m_end && run_len < npages; m += m_inc) {
KASSERT((m->flags & PG_MARKER) == 0,
("page %p is PG_MARKER", m));
@ -2489,9 +2470,8 @@ vm_page_scan_contig(u_long npages, vm_page_t m_start, vm_page_t m_end,
} else
KASSERT(m_run != NULL, ("m_run == NULL"));
vm_page_change_lock(m, &m_mtx);
m_inc = 1;
retry:
m_inc = 1;
if (vm_page_wired(m))
run_ext = 0;
#if VM_NRESERVLEVEL > 0
@ -2504,23 +2484,17 @@ vm_page_scan_contig(u_long npages, vm_page_t m_start, vm_page_t m_end,
pa);
}
#endif
else if ((object = m->object) != NULL) {
else if ((object =
(vm_object_t)atomic_load_ptr(&m->object)) != NULL) {
/*
* The page is considered eligible for relocation if
* and only if it could be laundered or reclaimed by
* the page daemon.
*/
if (!VM_OBJECT_TRYRLOCK(object)) {
mtx_unlock(m_mtx);
VM_OBJECT_RLOCK(object);
mtx_lock(m_mtx);
if (m->object != object) {
/*
* The page may have been freed.
*/
VM_OBJECT_RUNLOCK(object);
goto retry;
}
VM_OBJECT_RLOCK(object);
if (object != m->object) {
VM_OBJECT_RUNLOCK(object);
goto retry;
}
/* Don't care: PG_NODUMP, PG_ZERO. */
if (object->type != OBJT_DEFAULT &&
@ -2537,8 +2511,7 @@ vm_page_scan_contig(u_long npages, vm_page_t m_start, vm_page_t m_end,
vm_reserv_size(level)) - pa);
#endif
} else if (object->memattr == VM_MEMATTR_DEFAULT &&
vm_page_queue(m) != PQ_NONE && !vm_page_busied(m) &&
!vm_page_wired(m)) {
vm_page_queue(m) != PQ_NONE && !vm_page_busied(m)) {
/*
* The page is allocated but eligible for
* relocation. Extend the current run by one
@ -2605,8 +2578,6 @@ vm_page_scan_contig(u_long npages, vm_page_t m_start, vm_page_t m_end,
}
}
}
if (m_mtx != NULL)
mtx_unlock(m_mtx);
if (run_len >= npages)
return (m_run);
return (NULL);
@ -2634,7 +2605,6 @@ vm_page_reclaim_run(int req_class, int domain, u_long npages, vm_page_t m_run,
vm_paddr_t high)
{
struct vm_domain *vmd;
struct mtx *m_mtx;
struct spglist free;
vm_object_t object;
vm_paddr_t pa;
@ -2647,42 +2617,28 @@ vm_page_reclaim_run(int req_class, int domain, u_long npages, vm_page_t m_run,
error = 0;
m = m_run;
m_end = m_run + npages;
m_mtx = NULL;
for (; error == 0 && m < m_end; m++) {
KASSERT((m->flags & (PG_FICTITIOUS | PG_MARKER)) == 0,
("page %p is PG_FICTITIOUS or PG_MARKER", m));
/*
* Avoid releasing and reacquiring the same page lock.
*/
vm_page_change_lock(m, &m_mtx);
retry:
/*
* Racily check for wirings. Races are handled below.
* Racily check for wirings. Races are handled once the object
* lock is held and the page is unmapped.
*/
if (vm_page_wired(m))
error = EBUSY;
else if ((object = m->object) != NULL) {
else if ((object =
(vm_object_t)atomic_load_ptr(&m->object)) != NULL) {
/*
* The page is relocated if and only if it could be
* laundered or reclaimed by the page daemon.
*/
if (!VM_OBJECT_TRYWLOCK(object)) {
mtx_unlock(m_mtx);
VM_OBJECT_WLOCK(object);
mtx_lock(m_mtx);
if (m->object != object) {
/*
* The page may have been freed.
*/
VM_OBJECT_WUNLOCK(object);
goto retry;
}
}
VM_OBJECT_WLOCK(object);
/* Don't care: PG_NODUMP, PG_ZERO. */
if (object->type != OBJT_DEFAULT &&
if (m->object != object ||
(object->type != OBJT_DEFAULT &&
object->type != OBJT_SWAP &&
object->type != OBJT_VNODE)
object->type != OBJT_VNODE))
error = EINVAL;
else if (object->memattr != VM_MEMATTR_DEFAULT)
error = EINVAL;
@ -2781,7 +2737,6 @@ vm_page_reclaim_run(int req_class, int domain, u_long npages, vm_page_t m_run,
* The new page must be deactivated
* before the object is unlocked.
*/
vm_page_change_lock(m_new, &m_mtx);
vm_page_deactivate(m_new);
} else {
m->flags &= ~PG_ZERO;
@ -2821,8 +2776,6 @@ vm_page_reclaim_run(int req_class, int domain, u_long npages, vm_page_t m_run,
error = EINVAL;
}
}
if (m_mtx != NULL)
mtx_unlock(m_mtx);
if ((m = SLIST_FIRST(&free)) != NULL) {
int cnt;

View File

@ -609,7 +609,6 @@ vm_page_t vm_page_alloc_freelist(int, int);
vm_page_t vm_page_alloc_freelist_domain(int, int, int);
void vm_page_bits_set(vm_page_t m, vm_page_bits_t *bits, vm_page_bits_t set);
bool vm_page_blacklist_add(vm_paddr_t pa, bool verbose);
void vm_page_change_lock(vm_page_t m, struct mtx **mtx);
vm_page_t vm_page_grab (vm_object_t, vm_pindex_t, int);
int vm_page_grab_pages(vm_object_t object, vm_pindex_t pindex, int allocflags,
vm_page_t *ma, int count);

View File

@ -88,8 +88,12 @@ struct hwp_softc {
bool hwp_activity_window;
bool hwp_pref_ctrl;
bool hwp_pkg_ctrl;
bool hwp_pkg_ctrl_en;
bool hwp_perf_bias;
bool hwp_perf_bias_cached;
uint64_t req; /* Cached copy of last request */
uint64_t req; /* Cached copy of HWP_REQUEST */
uint64_t hwp_energy_perf_bias; /* Cache PERF_BIAS */
uint8_t high;
uint8_t guaranteed;
@ -108,6 +112,11 @@ DRIVER_MODULE(hwpstate_intel, cpu, hwpstate_intel_driver,
hwpstate_intel_devclass, NULL, NULL);
MODULE_VERSION(hwpstate_intel, 1);
static bool hwpstate_pkg_ctrl_enable = true;
SYSCTL_BOOL(_machdep, OID_AUTO, hwpstate_pkg_ctrl, CTLFLAG_RDTUN,
&hwpstate_pkg_ctrl_enable, 0,
"Set 1 (default) to enable package-level control, 0 to disable");
static int
intel_hwp_dump_sysctl_handler(SYSCTL_HANDLER_ARGS)
{
@ -215,16 +224,41 @@ raw_to_percent(int x)
return (round10(x * 1000 / 0xff));
}
/* Range of MSR_IA32_ENERGY_PERF_BIAS is more limited: 0-0xf. */
static inline int
percent_to_raw_perf_bias(int x)
{
/*
* Round up so that raw values present as nice round human numbers and
* also round-trip to the same raw value.
*/
MPASS(x <= 100 && x >= 0);
return (((0xf * x) + 50) / 100);
}
static inline int
raw_to_percent_perf_bias(int x)
{
/* Rounding to nice human numbers despite a step interval of 6.67%. */
MPASS(x <= 0xf && x >= 0);
return (((x * 20) / 0xf) * 5);
}
static int
sysctl_epp_select(SYSCTL_HANDLER_ARGS)
{
struct hwp_softc *sc;
device_t dev;
struct pcpu *pc;
uint64_t requested;
uint64_t epb;
uint32_t val;
int ret;
dev = oidp->oid_arg1;
sc = device_get_softc(dev);
if (!sc->hwp_pref_ctrl && !sc->hwp_perf_bias)
return (ENODEV);
pc = cpu_get_pcpu(dev);
if (pc == NULL)
return (ENXIO);
@ -233,9 +267,26 @@ sysctl_epp_select(SYSCTL_HANDLER_ARGS)
sched_bind(curthread, pc->pc_cpuid);
thread_unlock(curthread);
rdmsr_safe(MSR_IA32_HWP_REQUEST, &requested);
val = (requested & IA32_HWP_REQUEST_ENERGY_PERFORMANCE_PREFERENCE) >> 24;
val = raw_to_percent(val);
if (sc->hwp_pref_ctrl) {
val = (sc->req & IA32_HWP_REQUEST_ENERGY_PERFORMANCE_PREFERENCE) >> 24;
val = raw_to_percent(val);
} else {
/*
* If cpuid indicates EPP is not supported, the HWP controller
* uses MSR_IA32_ENERGY_PERF_BIAS instead (Intel SDM §14.4.4).
* This register is per-core (but not HT).
*/
if (!sc->hwp_perf_bias_cached) {
ret = rdmsr_safe(MSR_IA32_ENERGY_PERF_BIAS, &epb);
if (ret)
goto out;
sc->hwp_energy_perf_bias = epb;
sc->hwp_perf_bias_cached = true;
}
val = sc->hwp_energy_perf_bias &
IA32_ENERGY_PERF_BIAS_POLICY_HINT_MASK;
val = raw_to_percent_perf_bias(val);
}
MPASS(val >= 0 && val <= 100);
@ -248,12 +299,27 @@ sysctl_epp_select(SYSCTL_HANDLER_ARGS)
goto out;
}
val = percent_to_raw(val);
if (sc->hwp_pref_ctrl) {
val = percent_to_raw(val);
requested &= ~IA32_HWP_REQUEST_ENERGY_PERFORMANCE_PREFERENCE;
requested |= val << 24;
sc->req =
((sc->req & ~IA32_HWP_REQUEST_ENERGY_PERFORMANCE_PREFERENCE)
| (val << 24u));
wrmsr_safe(MSR_IA32_HWP_REQUEST, requested);
if (sc->hwp_pkg_ctrl_en)
ret = wrmsr_safe(MSR_IA32_HWP_REQUEST_PKG, sc->req);
else
ret = wrmsr_safe(MSR_IA32_HWP_REQUEST, sc->req);
} else {
val = percent_to_raw_perf_bias(val);
MPASS((val & ~IA32_ENERGY_PERF_BIAS_POLICY_HINT_MASK) == 0);
sc->hwp_energy_perf_bias =
((sc->hwp_energy_perf_bias &
~IA32_ENERGY_PERF_BIAS_POLICY_HINT_MASK) | val);
ret = wrmsr_safe(MSR_IA32_ENERGY_PERF_BIAS,
sc->hwp_energy_perf_bias);
}
out:
thread_lock(curthread);
@ -266,8 +332,6 @@ sysctl_epp_select(SYSCTL_HANDLER_ARGS)
void
intel_hwpstate_identify(driver_t *driver, device_t parent)
{
uint32_t regs[4];
if (device_find_child(parent, "hwpstate_intel", -1) != NULL)
return;
@ -277,17 +341,6 @@ intel_hwpstate_identify(driver_t *driver, device_t parent)
if (resource_disabled("hwpstate_intel", 0))
return;
/*
* Intel SDM 14.4.1 (HWP Programming Interfaces):
* The CPUID instruction allows software to discover the presence of
* HWP support in an Intel processor. Specifically, execute CPUID
* instruction with EAX=06H as input will return 5 bit flags covering
* the following aspects in bits 7 through 11 of CPUID.06H:EAX.
*/
if (cpu_high < 6)
return;
/*
* Intel SDM 14.4.1 (HWP Programming Interfaces):
* Availability of HWP baseline resource and capability,
@ -295,9 +348,7 @@ intel_hwpstate_identify(driver_t *driver, device_t parent)
* architectural MSRs: IA32_PM_ENABLE, IA32_HWP_CAPABILITIES,
* IA32_HWP_REQUEST, IA32_HWP_STATUS.
*/
do_cpuid(6, regs);
if ((regs[0] & CPUTPM1_HWP) == 0)
if ((cpu_power_eax & CPUTPM1_HWP) == 0)
return;
if (BUS_ADD_CHILD(parent, 10, "hwpstate_intel", -1) == NULL)
@ -315,7 +366,6 @@ intel_hwpstate_probe(device_t dev)
return (BUS_PROBE_NOWILDCARD);
}
/* FIXME: Need to support PKG variant */
static int
set_autonomous_hwp(struct hwp_softc *sc)
{
@ -337,19 +387,39 @@ set_autonomous_hwp(struct hwp_softc *sc)
/* XXX: Many MSRs aren't readable until feature is enabled */
ret = wrmsr_safe(MSR_IA32_PM_ENABLE, 1);
if (ret) {
/*
* This is actually a package-level MSR, and only the first
* write is not ignored. So it is harmless to enable it across
* all devices, and this allows us not to care especially in
* which order cores (and packages) are probed. This error
* condition should not happen given we gate on the HWP CPUID
* feature flag, if the Intel SDM is correct.
*/
device_printf(dev, "Failed to enable HWP for cpu%d (%d)\n",
pc->pc_cpuid, ret);
goto out;
}
ret = rdmsr_safe(MSR_IA32_HWP_REQUEST, &sc->req);
if (ret)
return (ret);
if (ret) {
device_printf(dev,
"Failed to read HWP request MSR for cpu%d (%d)\n",
pc->pc_cpuid, ret);
goto out;
}
ret = rdmsr_safe(MSR_IA32_HWP_CAPABILITIES, &caps);
if (ret)
return (ret);
if (ret) {
device_printf(dev,
"Failed to read HWP capabilities MSR for cpu%d (%d)\n",
pc->pc_cpuid, ret);
goto out;
}
/*
* High and low are static; "guaranteed" is dynamic; and efficient is
* also dynamic.
*/
sc->high = IA32_HWP_CAPABILITIES_HIGHEST_PERFORMANCE(caps);
sc->guaranteed = IA32_HWP_CAPABILITIES_GUARANTEED_PERFORMANCE(caps);
sc->efficient = IA32_HWP_CAPABILITIES_EFFICIENT_PERFORMANCE(caps);
@ -369,11 +439,30 @@ set_autonomous_hwp(struct hwp_softc *sc)
sc->req &= ~IA32_HWP_REQUEST_MAXIMUM_PERFORMANCE;
sc->req |= sc->high << 8;
ret = wrmsr_safe(MSR_IA32_HWP_REQUEST, sc->req);
/* If supported, request package-level control for this CPU. */
if (sc->hwp_pkg_ctrl_en)
ret = wrmsr_safe(MSR_IA32_HWP_REQUEST, sc->req |
IA32_HWP_REQUEST_PACKAGE_CONTROL);
else
ret = wrmsr_safe(MSR_IA32_HWP_REQUEST, sc->req);
if (ret) {
device_printf(dev,
"Failed to setup autonomous HWP for cpu%d (file a bug)\n",
pc->pc_cpuid);
"Failed to setup%s autonomous HWP for cpu%d\n",
sc->hwp_pkg_ctrl_en ? " PKG" : "", pc->pc_cpuid);
goto out;
}
/* If supported, write the PKG-wide control MSR. */
if (sc->hwp_pkg_ctrl_en) {
/*
* "The structure of the IA32_HWP_REQUEST_PKG MSR
* (package-level) is identical to the IA32_HWP_REQUEST MSR
* with the exception of the Package Control field, which does
* not exist." (Intel SDM §14.4.4)
*/
ret = wrmsr_safe(MSR_IA32_HWP_REQUEST_PKG, sc->req);
device_printf(dev,
"Failed to set autonomous HWP for package\n");
}
out:
@ -388,22 +477,28 @@ static int
intel_hwpstate_attach(device_t dev)
{
struct hwp_softc *sc;
uint32_t regs[4];
int ret;
sc = device_get_softc(dev);
sc->dev = dev;
do_cpuid(6, regs);
if (regs[0] & CPUTPM1_HWP_NOTIFICATION)
/* eax */
if (cpu_power_eax & CPUTPM1_HWP_NOTIFICATION)
sc->hwp_notifications = true;
if (regs[0] & CPUTPM1_HWP_ACTIVITY_WINDOW)
if (cpu_power_eax & CPUTPM1_HWP_ACTIVITY_WINDOW)
sc->hwp_activity_window = true;
if (regs[0] & CPUTPM1_HWP_PERF_PREF)
if (cpu_power_eax & CPUTPM1_HWP_PERF_PREF)
sc->hwp_pref_ctrl = true;
if (regs[0] & CPUTPM1_HWP_PKG)
if (cpu_power_eax & CPUTPM1_HWP_PKG)
sc->hwp_pkg_ctrl = true;
/* Allow administrators to disable pkg-level control. */
sc->hwp_pkg_ctrl_en = (sc->hwp_pkg_ctrl && hwpstate_pkg_ctrl_enable);
/* ecx */
if (cpu_power_ecx & CPUID_PERF_BIAS)
sc->hwp_perf_bias = true;
ret = set_autonomous_hwp(sc);
if (ret)
return (ret);
@ -503,11 +598,34 @@ intel_hwpstate_resume(device_t dev)
goto out;
}
ret = wrmsr_safe(MSR_IA32_HWP_REQUEST, sc->req);
if (sc->hwp_pkg_ctrl_en)
ret = wrmsr_safe(MSR_IA32_HWP_REQUEST, sc->req |
IA32_HWP_REQUEST_PACKAGE_CONTROL);
else
ret = wrmsr_safe(MSR_IA32_HWP_REQUEST, sc->req);
if (ret) {
device_printf(dev,
"Failed to setup autonomous HWP for cpu%d after suspend\n",
pc->pc_cpuid);
"Failed to set%s autonomous HWP for cpu%d after suspend\n",
sc->hwp_pkg_ctrl_en ? " PKG" : "", pc->pc_cpuid);
goto out;
}
if (sc->hwp_pkg_ctrl_en) {
ret = wrmsr_safe(MSR_IA32_HWP_REQUEST_PKG, sc->req);
if (ret) {
device_printf(dev,
"Failed to set autonomous HWP for package after "
"suspend\n");
goto out;
}
}
if (!sc->hwp_pref_ctrl && sc->hwp_perf_bias_cached) {
ret = wrmsr_safe(MSR_IA32_ENERGY_PERF_BIAS,
sc->hwp_energy_perf_bias);
if (ret) {
device_printf(dev,
"Failed to set energy perf bias for cpu%d after "
"suspend\n", pc->pc_cpuid);
}
}
out:

View File

@ -566,6 +566,7 @@
#define MSR_IA32_TEMPERATURE_TARGET 0x1a2
#define MSR_TURBO_RATIO_LIMIT 0x1ad
#define MSR_TURBO_RATIO_LIMIT1 0x1ae
#define MSR_IA32_ENERGY_PERF_BIAS 0x1b0
#define MSR_DEBUGCTLMSR 0x1d9
#define MSR_LASTBRANCHFROMIP 0x1db
#define MSR_LASTBRANCHTOIP 0x1dc
@ -811,6 +812,9 @@
#define IA32_HWP_REQUEST_MAXIMUM_PERFORMANCE (0xffULL << 8)
#define IA32_HWP_MINIMUM_PERFORMANCE (0xffULL << 0)
/* MSR IA32_ENERGY_PERF_BIAS */
#define IA32_ENERGY_PERF_BIAS_POLICY_HINT_MASK (0xfULL << 0)
/*
* PAT modes.
*/

View File

@ -119,9 +119,9 @@ u_int cpu_mon_min_size; /* MONITOR minimum range size, bytes */
u_int cpu_mon_max_size; /* MONITOR minimum range size, bytes */
u_int cpu_maxphyaddr; /* Max phys addr width in bits */
u_int cpu_power_eax; /* 06H: Power management leaf, %eax */
u_int cpu_power_ebx; /* 06H: Power management leaf, %eax */
u_int cpu_power_ecx; /* 06H: Power management leaf, %eax */
u_int cpu_power_edx; /* 06H: Power management leaf, %eax */
u_int cpu_power_ebx; /* 06H: Power management leaf, %ebx */
u_int cpu_power_ecx; /* 06H: Power management leaf, %ecx */
u_int cpu_power_edx; /* 06H: Power management leaf, %edx */
char machine[] = MACHINE;
SYSCTL_UINT(_hw, OID_AUTO, via_feature_rng, CTLFLAG_RD,

View File

@ -53,7 +53,7 @@ ATF_TC_BODY(params, tc)
int s;
s = kldload("if_epair");
if (s != 0 && errno != EEXIST)
if (s == -1 && errno != EEXIST)
atf_tc_fail("Failed to load if_epair");
s = socket(AF_INET, SOCK_DGRAM, 0);