Restore the ABI of the cpuctl(4) ioctl request CPUCTL_CPUID, use

separate argument structure with added level_type field for
CPUID_CPUID_COUNT request.

Reviewed by:	attilio (previous version)
Sponsored by:	The FreeBSD Foundation
MFC after:	2 weeks
This commit is contained in:
Konstantin Belousov 2014-06-20 13:13:38 +00:00
parent 8c0ddf28da
commit cef789cd61
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=267673
4 changed files with 63 additions and 21 deletions

View File

@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd June 30, 2009
.Dd June 20, 2014
.Dt CPUCTL 4
.Os
.Sh NAME
@ -65,7 +65,7 @@ All of the supported operations are invoked using the
.Xr ioctl 2
system call.
Currently, the following ioctls are defined:
.Bl -tag -width CPUCTL_UPDATE
.Bl -tag -width CPUCTL_CPUID_COUNT
.It Dv CPUCTL_RDMSR Fa cpuctl_msr_args_t *args
.It Dv CPUCTL_WRMSR Fa cpuctl_msr_args_t *args
Read/write CPU machine specific register.
@ -86,29 +86,60 @@ Set/clear MSR bits according to the mask given in the
.Va data
field.
.It Dv CPUCTL_CPUID Fa cpuctl_cpuid_args_t *args
.It Dv CPUCTL_CPUID_COUNT Fa cpuctl_cpuid_args_t *args
Retrieve CPUID information.
Arguments are supplied in
the following struct:
Arguments are supplied in the following structure:
.Bd -literal
typedef struct {
int level; /* CPUID level */
uint32_t data[4];
} cpuctl_cpuid_args_t;
.Ed
It is equivalent to the
.Dv CPUCTL_CPUID_COUNT
request with
.Va level_type
set to 0.
.It Dv CPUCTL_CPUID_COUNT Fa cpuctl_cpuid_count_args_t *args
Retrieve CPUID information.
Arguments are supplied in the following structure:
.Bd -literal
typedef struct {
int level; /* CPUID level */
int level_type; /* CPUID level type */
uint32_t data[4];
} cpuctl_cpuid_args_t;
} cpuctl_cpuid_count_args_t;
.Ed
.Pp
The
.Va level
field indicates the CPUID level to retrieve.
field indicates the CPUID level to retrieve,
it is loaded into the
.Va %eax
register before the CPUID instruction is executed,
The
.Va level_type
field indicates the CPUID level type to retrieve.
It is overriden to 0 for
.Va CPUCTL_CPUID .
Finally, the
field indicates the CPUID level type to retrieve,
it is loaded into the
.Va %ecx
register.
.Pp
The
.Va data
field is used to store the received CPUID data.
That is,
.Va data[0]
contains the value of
.Va %eax
register after the CPUID instruction is executed,
.Va data[1]
is for
.Va %ebx ,
.Va data[2]
for
.Va %ecx ,
and
.Va data[3]
for
.Va %edx .
.It Dv CPUCTL_UPDATE cpuctl_update_args_t *args
Update CPU firmware (microcode).
The structure is defined in

View File

@ -69,7 +69,7 @@ static int cpuctl_do_msr(int cpu, cpuctl_msr_args_t *data, u_long cmd,
struct thread *td);
static int cpuctl_do_cpuid(int cpu, cpuctl_cpuid_args_t *data,
struct thread *td);
static int cpuctl_do_cpuid_count(int cpu, cpuctl_cpuid_args_t *data,
static int cpuctl_do_cpuid_count(int cpu, cpuctl_cpuid_count_args_t *data,
struct thread *td);
static int cpuctl_do_update(int cpu, cpuctl_update_args_t *data,
struct thread *td);
@ -180,8 +180,8 @@ cpuctl_ioctl(struct cdev *dev, u_long cmd, caddr_t data,
ret = cpuctl_do_update(cpu, (cpuctl_update_args_t *)data, td);
break;
case CPUCTL_CPUID_COUNT:
ret = cpuctl_do_cpuid_count(cpu, (cpuctl_cpuid_args_t *)data,
td);
ret = cpuctl_do_cpuid_count(cpu,
(cpuctl_cpuid_count_args_t *)data, td);
break;
default:
ret = EINVAL;
@ -195,7 +195,8 @@ cpuctl_ioctl(struct cdev *dev, u_long cmd, caddr_t data,
* Actually perform cpuid operation.
*/
static int
cpuctl_do_cpuid_count(int cpu, cpuctl_cpuid_args_t *data, struct thread *td)
cpuctl_do_cpuid_count(int cpu, cpuctl_cpuid_count_args_t *data,
struct thread *td)
{
int is_bound = 0;
int oldcpu;
@ -218,10 +219,15 @@ cpuctl_do_cpuid_count(int cpu, cpuctl_cpuid_args_t *data, struct thread *td)
static int
cpuctl_do_cpuid(int cpu, cpuctl_cpuid_args_t *data, struct thread *td)
{
cpuctl_cpuid_count_args_t cdata;
int error;
cdata.level = data->level;
/* Override the level type. */
data->level_type = 0;
return (cpuctl_do_cpuid_count(cpu, data, td));
cdata.level_type = 0;
error = cpuctl_do_cpuid_count(cpu, &cdata, td);
bcopy(cdata.data, data->data, sizeof(data->data)); /* Ignore error */
return (error);
}
/*

View File

@ -36,10 +36,15 @@ typedef struct {
typedef struct {
int level; /* CPUID level */
int level_type; /* CPUID level type */
uint32_t data[4];
} cpuctl_cpuid_args_t;
typedef struct {
int level; /* CPUID level */
int level_type; /* CPUID level type */
uint32_t data[4];
} cpuctl_cpuid_count_args_t;
typedef struct {
void *data;
size_t size;
@ -51,6 +56,6 @@ typedef struct {
#define CPUCTL_UPDATE _IOWR('c', 4, cpuctl_update_args_t)
#define CPUCTL_MSRSBIT _IOWR('c', 5, 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)
#define CPUCTL_CPUID_COUNT _IOWR('c', 7, cpuctl_cpuid_count_args_t)
#endif /* _CPUCTL_H_ */

View File

@ -175,7 +175,7 @@ do_cpuid_count(const char *cmdarg, const char *dev)
{
char *cmdarg1, *endptr, *endptr1;
unsigned int level, level_type;
cpuctl_cpuid_args_t args;
cpuctl_cpuid_count_args_t args;
int fd, error;
assert(cmdarg != NULL);