diff --git a/share/man/man4/cpuctl.4 b/share/man/man4/cpuctl.4 index 3aff1e3c11d5..3cc0138325dd 100644 --- a/share/man/man4/cpuctl.4 +++ b/share/man/man4/cpuctl.4 @@ -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 diff --git a/sys/dev/cpuctl/cpuctl.c b/sys/dev/cpuctl/cpuctl.c index 63187bdc4b8b..9832933d0c91 100644 --- a/sys/dev/cpuctl/cpuctl.c +++ b/sys/dev/cpuctl/cpuctl.c @@ -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 @@ fail: * 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); } /* diff --git a/sys/sys/cpuctl.h b/sys/sys/cpuctl.h index 4220dee33186..30af52405c66 100644 --- a/sys/sys/cpuctl.h +++ b/sys/sys/cpuctl.h @@ -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_ */ diff --git a/usr.sbin/cpucontrol/cpucontrol.c b/usr.sbin/cpucontrol/cpucontrol.c index 9832d9fd0706..69fdf3aa76f2 100644 --- a/usr.sbin/cpucontrol/cpucontrol.c +++ b/usr.sbin/cpucontrol/cpucontrol.c @@ -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);