Following comments in r242565 add the possibility to specify ecx when
performing cpuid calls. Add also a new way to specify the level type to cpucontrol(8) as reported in the manpage. Sponsored by: EMC / Isilon storage division Reviewed by: bdrewery, gcooper Testerd by: bdrewery
This commit is contained in:
parent
39c18ce157
commit
aa1cb7501f
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=267651
@ -86,19 +86,27 @@ Set/clear MSR bits according to the mask given in the
|
|||||||
.Va data
|
.Va data
|
||||||
field.
|
field.
|
||||||
.It Dv CPUCTL_CPUID Fa cpuctl_cpuid_args_t *args
|
.It Dv CPUCTL_CPUID Fa cpuctl_cpuid_args_t *args
|
||||||
|
.It Dv CPUCTL_CPUID_COUNT Fa cpuctl_cpuid_args_t *args
|
||||||
Retrieve CPUID information.
|
Retrieve CPUID information.
|
||||||
Arguments are supplied in
|
Arguments are supplied in
|
||||||
the following struct:
|
the following struct:
|
||||||
.Bd -literal
|
.Bd -literal
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int level; /* CPUID level */
|
int level; /* CPUID level */
|
||||||
|
int level_type; /* CPUID level type */
|
||||||
uint32_t data[4];
|
uint32_t data[4];
|
||||||
} cpuctl_cpuid_args_t;
|
} cpuctl_cpuid_args_t;
|
||||||
.Ed
|
.Ed
|
||||||
.Pp
|
.Pp
|
||||||
The
|
The
|
||||||
.Va level
|
.Va level
|
||||||
field indicates the CPUID level to retrieve information for, while the
|
field indicates the CPUID level to retrieve.
|
||||||
|
The
|
||||||
|
.Va level_type
|
||||||
|
field indicates the CPUID level type to retrieve.
|
||||||
|
It is overriden to 0 for
|
||||||
|
.Va CPUCTL_CPUID .
|
||||||
|
Finally, the
|
||||||
.Va data
|
.Va data
|
||||||
field is used to store the received CPUID data.
|
field is used to store the received CPUID data.
|
||||||
.It Dv CPUCTL_UPDATE cpuctl_update_args_t *args
|
.It Dv CPUCTL_UPDATE cpuctl_update_args_t *args
|
||||||
|
@ -69,6 +69,8 @@ static int cpuctl_do_msr(int cpu, cpuctl_msr_args_t *data, u_long cmd,
|
|||||||
struct thread *td);
|
struct thread *td);
|
||||||
static int cpuctl_do_cpuid(int cpu, cpuctl_cpuid_args_t *data,
|
static int cpuctl_do_cpuid(int cpu, cpuctl_cpuid_args_t *data,
|
||||||
struct thread *td);
|
struct thread *td);
|
||||||
|
static int cpuctl_do_cpuid_count(int cpu, cpuctl_cpuid_args_t *data,
|
||||||
|
struct thread *td);
|
||||||
static int cpuctl_do_update(int cpu, cpuctl_update_args_t *data,
|
static int cpuctl_do_update(int cpu, cpuctl_update_args_t *data,
|
||||||
struct thread *td);
|
struct thread *td);
|
||||||
static int update_intel(int cpu, cpuctl_update_args_t *args,
|
static int update_intel(int cpu, cpuctl_update_args_t *args,
|
||||||
@ -177,6 +179,10 @@ cpuctl_ioctl(struct cdev *dev, u_long cmd, caddr_t data,
|
|||||||
goto fail;
|
goto fail;
|
||||||
ret = cpuctl_do_update(cpu, (cpuctl_update_args_t *)data, td);
|
ret = cpuctl_do_update(cpu, (cpuctl_update_args_t *)data, td);
|
||||||
break;
|
break;
|
||||||
|
case CPUCTL_CPUID_COUNT:
|
||||||
|
ret = cpuctl_do_cpuid_count(cpu, (cpuctl_cpuid_args_t *)data,
|
||||||
|
td);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
ret = EINVAL;
|
ret = EINVAL;
|
||||||
break;
|
break;
|
||||||
@ -189,7 +195,7 @@ cpuctl_ioctl(struct cdev *dev, u_long cmd, caddr_t data,
|
|||||||
* Actually perform cpuid operation.
|
* Actually perform cpuid operation.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
cpuctl_do_cpuid(int cpu, cpuctl_cpuid_args_t *data, struct thread *td)
|
cpuctl_do_cpuid_count(int cpu, cpuctl_cpuid_args_t *data, struct thread *td)
|
||||||
{
|
{
|
||||||
int is_bound = 0;
|
int is_bound = 0;
|
||||||
int oldcpu;
|
int oldcpu;
|
||||||
@ -199,16 +205,25 @@ cpuctl_do_cpuid(int cpu, cpuctl_cpuid_args_t *data, struct thread *td)
|
|||||||
|
|
||||||
/* Explicitly clear cpuid data to avoid returning stale info. */
|
/* Explicitly clear cpuid data to avoid returning stale info. */
|
||||||
bzero(data->data, sizeof(data->data));
|
bzero(data->data, sizeof(data->data));
|
||||||
DPRINTF("[cpuctl,%d]: retriving cpuid level %#0x for %d cpu\n",
|
DPRINTF("[cpuctl,%d]: retrieving cpuid lev %#0x type %#0x for %d cpu\n",
|
||||||
__LINE__, data->level, cpu);
|
__LINE__, data->level, data->level_type, cpu);
|
||||||
oldcpu = td->td_oncpu;
|
oldcpu = td->td_oncpu;
|
||||||
is_bound = cpu_sched_is_bound(td);
|
is_bound = cpu_sched_is_bound(td);
|
||||||
set_cpu(cpu, td);
|
set_cpu(cpu, td);
|
||||||
cpuid_count(data->level, 0, data->data);
|
cpuid_count(data->level, data->level_type, data->data);
|
||||||
restore_cpu(oldcpu, is_bound, td);
|
restore_cpu(oldcpu, is_bound, td);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
cpuctl_do_cpuid(int cpu, cpuctl_cpuid_args_t *data, struct thread *td)
|
||||||
|
{
|
||||||
|
|
||||||
|
/* Override the level type. */
|
||||||
|
data->level_type = 0;
|
||||||
|
return (cpuctl_do_cpuid_count(cpu, data, td));
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Actually perform MSR operations.
|
* Actually perform MSR operations.
|
||||||
*/
|
*/
|
||||||
|
@ -35,7 +35,8 @@ typedef struct {
|
|||||||
} cpuctl_msr_args_t;
|
} cpuctl_msr_args_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int level; /* CPUID level */
|
int level; /* CPUID level */
|
||||||
|
int level_type; /* CPUID level type */
|
||||||
uint32_t data[4];
|
uint32_t data[4];
|
||||||
} cpuctl_cpuid_args_t;
|
} cpuctl_cpuid_args_t;
|
||||||
|
|
||||||
@ -50,5 +51,6 @@ typedef struct {
|
|||||||
#define CPUCTL_UPDATE _IOWR('c', 4, cpuctl_update_args_t)
|
#define CPUCTL_UPDATE _IOWR('c', 4, cpuctl_update_args_t)
|
||||||
#define CPUCTL_MSRSBIT _IOWR('c', 5, cpuctl_msr_args_t)
|
#define CPUCTL_MSRSBIT _IOWR('c', 5, cpuctl_msr_args_t)
|
||||||
#define CPUCTL_MSRCBIT _IOWR('c', 6, cpuctl_msr_args_t)
|
#define CPUCTL_MSRCBIT _IOWR('c', 6, cpuctl_msr_args_t)
|
||||||
|
#define CPUCTL_CPUID_COUNT _IOWR('c', 7, cpuctl_cpuid_args_t)
|
||||||
|
|
||||||
#endif /* _CPUCTL_H_ */
|
#endif /* _CPUCTL_H_ */
|
||||||
|
@ -65,6 +65,12 @@ device
|
|||||||
.Ek
|
.Ek
|
||||||
.Nm
|
.Nm
|
||||||
.Op Fl vh
|
.Op Fl vh
|
||||||
|
.Fl i Ar level,level_type
|
||||||
|
.Bk
|
||||||
|
.Ar device
|
||||||
|
.Ek
|
||||||
|
.Nm
|
||||||
|
.Op Fl vh
|
||||||
.Op Fl d Ar datadir
|
.Op Fl d Ar datadir
|
||||||
.Fl u
|
.Fl u
|
||||||
.Bk
|
.Bk
|
||||||
@ -114,6 +120,9 @@ In this case the inverted value of mask will be used.
|
|||||||
.It Fl i Ar level
|
.It Fl i Ar level
|
||||||
Retrieve CPUID info.
|
Retrieve CPUID info.
|
||||||
Level should be given as a hex number.
|
Level should be given as a hex number.
|
||||||
|
.It Fl i Ar level,level_type
|
||||||
|
Retrieve CPUID info.
|
||||||
|
Level and level_type should be given as hex numbers.
|
||||||
.It Fl u
|
.It Fl u
|
||||||
Apply CPU firmware updates.
|
Apply CPU firmware updates.
|
||||||
The
|
The
|
||||||
|
@ -99,6 +99,7 @@ static struct ucode_handler {
|
|||||||
static void usage(void);
|
static void usage(void);
|
||||||
static int isdir(const char *path);
|
static int isdir(const char *path);
|
||||||
static int do_cpuid(const char *cmdarg, const char *dev);
|
static int do_cpuid(const char *cmdarg, const char *dev);
|
||||||
|
static int do_cpuid_count(const char *cmdarg, const char *dev);
|
||||||
static int do_msr(const char *cmdarg, const char *dev);
|
static int do_msr(const char *cmdarg, const char *dev);
|
||||||
static int do_update(const char *dev);
|
static int do_update(const char *dev);
|
||||||
static void datadir_add(const char *path);
|
static void datadir_add(const char *path);
|
||||||
@ -112,7 +113,7 @@ usage(void)
|
|||||||
if (name == NULL)
|
if (name == NULL)
|
||||||
name = "cpuctl";
|
name = "cpuctl";
|
||||||
fprintf(stderr, "Usage: %s [-vh] [-d datadir] [-m msr[=value] | "
|
fprintf(stderr, "Usage: %s [-vh] [-d datadir] [-m msr[=value] | "
|
||||||
"-i level | -u] device\n", name);
|
"-i level | -i level,level_type | -u] device\n", name);
|
||||||
exit(EX_USAGE);
|
exit(EX_USAGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -169,6 +170,57 @@ do_cpuid(const char *cmdarg, const char *dev)
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
do_cpuid_count(const char *cmdarg, const char *dev)
|
||||||
|
{
|
||||||
|
char *cmdarg1, *endptr, *endptr1;
|
||||||
|
unsigned int level, level_type;
|
||||||
|
cpuctl_cpuid_args_t args;
|
||||||
|
int fd, error;
|
||||||
|
|
||||||
|
assert(cmdarg != NULL);
|
||||||
|
assert(dev != NULL);
|
||||||
|
|
||||||
|
level = strtoul(cmdarg, &endptr, 16);
|
||||||
|
if (*cmdarg == '\0' || *endptr == '\0') {
|
||||||
|
WARNX(0, "incorrect or missing operand: %s", cmdarg);
|
||||||
|
usage();
|
||||||
|
/* NOTREACHED */
|
||||||
|
}
|
||||||
|
/* Locate the comma... */
|
||||||
|
cmdarg1 = strstr(endptr, ",");
|
||||||
|
/* ... and skip past it */
|
||||||
|
cmdarg1 += 1;
|
||||||
|
level_type = strtoul(cmdarg1, &endptr1, 16);
|
||||||
|
if (*cmdarg1 == '\0' || *endptr1 != '\0') {
|
||||||
|
WARNX(0, "incorrect or missing operand: %s", cmdarg);
|
||||||
|
usage();
|
||||||
|
/* NOTREACHED */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fill ioctl argument structure.
|
||||||
|
*/
|
||||||
|
args.level = level;
|
||||||
|
args.level_type = level_type;
|
||||||
|
fd = open(dev, O_RDONLY);
|
||||||
|
if (fd < 0) {
|
||||||
|
WARN(0, "error opening %s for reading", dev);
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
error = ioctl(fd, CPUCTL_CPUID_COUNT, &args);
|
||||||
|
if (error < 0) {
|
||||||
|
WARN(0, "ioctl(%s, CPUCTL_CPUID_COUNT)", dev);
|
||||||
|
close(fd);
|
||||||
|
return (error);
|
||||||
|
}
|
||||||
|
fprintf(stdout, "cpuid level 0x%x, level_type 0x%x: 0x%.8x 0x%.8x "
|
||||||
|
"0x%.8x 0x%.8x\n", level, level_type, args.data[0], args.data[1],
|
||||||
|
args.data[2], args.data[3]);
|
||||||
|
close(fd);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
do_msr(const char *cmdarg, const char *dev)
|
do_msr(const char *cmdarg, const char *dev)
|
||||||
{
|
{
|
||||||
@ -414,7 +466,10 @@ main(int argc, char *argv[])
|
|||||||
c = flags & (FLAG_I | FLAG_M | FLAG_U);
|
c = flags & (FLAG_I | FLAG_M | FLAG_U);
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case FLAG_I:
|
case FLAG_I:
|
||||||
error = do_cpuid(cmdarg, dev);
|
if (strstr(cmdarg, ",") != NULL)
|
||||||
|
error = do_cpuid_count(cmdarg, dev);
|
||||||
|
else
|
||||||
|
error = do_cpuid(cmdarg, dev);
|
||||||
break;
|
break;
|
||||||
case FLAG_M:
|
case FLAG_M:
|
||||||
error = do_msr(cmdarg, dev);
|
error = do_msr(cmdarg, dev);
|
||||||
|
Loading…
Reference in New Issue
Block a user