svn commit: r268157 - in stable/10: share/man/man4 sys/dev/cpuctl sys/sys usr.sbin/cpucontrol

Konstantin Belousov kib at FreeBSD.org
Wed Jul 2 13:09:27 UTC 2014


Author: kib
Date: Wed Jul  2 13:09:26 2014
New Revision: 268157
URL: http://svnweb.freebsd.org/changeset/base/268157

Log:
  MFC r267651 (by attilio):
  Add the possibility to specify ecx when performing cpuid calls.
  
  MFC r267673:
  Restore the ABI of the cpuctl(4) ioctl request CPUCTL_CPUID.
  
  MFC r267814:
  Make cpuctl_do_cpuid() and cpuctl_do_cpuid_count() return void.

Modified:
  stable/10/share/man/man4/cpuctl.4
  stable/10/sys/dev/cpuctl/cpuctl.c
  stable/10/sys/sys/cpuctl.h
  stable/10/usr.sbin/cpucontrol/cpucontrol.8
  stable/10/usr.sbin/cpucontrol/cpucontrol.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/share/man/man4/cpuctl.4
==============================================================================
--- stable/10/share/man/man4/cpuctl.4	Wed Jul  2 12:13:11 2014	(r268156)
+++ stable/10/share/man/man4/cpuctl.4	Wed Jul  2 13:09:26 2014	(r268157)
@@ -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 invo
 .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.
@@ -87,20 +87,59 @@ Set/clear MSR bits according to the mask
 field.
 .It Dv CPUCTL_CPUID 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 */
+	int		level;		/* CPUID level */
 	uint32_t	data[4];
 } cpuctl_cpuid_args_t;
 .Ed
-.Pp
+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_count_args_t;
+.Ed
 The
 .Va level
-field indicates the CPUID level to retrieve information for, while the
+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 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

Modified: stable/10/sys/dev/cpuctl/cpuctl.c
==============================================================================
--- stable/10/sys/dev/cpuctl/cpuctl.c	Wed Jul  2 12:13:11 2014	(r268156)
+++ stable/10/sys/dev/cpuctl/cpuctl.c	Wed Jul  2 13:09:26 2014	(r268157)
@@ -67,7 +67,9 @@ static d_ioctl_t cpuctl_ioctl;
 
 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,
+static void cpuctl_do_cpuid(int cpu, cpuctl_cpuid_args_t *data,
+    struct thread *td);
+static void 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);
@@ -169,7 +171,8 @@ cpuctl_ioctl(struct cdev *dev, u_long cm
 		ret = cpuctl_do_msr(cpu, (cpuctl_msr_args_t *)data, cmd, td);
 		break;
 	case CPUCTL_CPUID:
-		ret = cpuctl_do_cpuid(cpu, (cpuctl_cpuid_args_t *)data, td);
+		cpuctl_do_cpuid(cpu, (cpuctl_cpuid_args_t *)data, td);
+		ret = 0;
 		break;
 	case CPUCTL_UPDATE:
 		ret = priv_check(td, PRIV_CPUCTL_UPDATE);
@@ -177,6 +180,11 @@ cpuctl_ioctl(struct cdev *dev, u_long cm
 			goto fail;
 		ret = cpuctl_do_update(cpu, (cpuctl_update_args_t *)data, td);
 		break;
+	case CPUCTL_CPUID_COUNT:
+		cpuctl_do_cpuid_count(cpu, (cpuctl_cpuid_count_args_t *)data,
+		    td);
+		ret = 0;
+		break;
 	default:
 		ret = EINVAL;
 		break;
@@ -188,8 +196,9 @@ fail:
 /*
  * Actually perform cpuid operation.
  */
-static int
-cpuctl_do_cpuid(int cpu, cpuctl_cpuid_args_t *data, struct thread *td)
+static void
+cpuctl_do_cpuid_count(int cpu, cpuctl_cpuid_count_args_t *data,
+    struct thread *td)
 {
 	int is_bound = 0;
 	int oldcpu;
@@ -199,14 +208,25 @@ cpuctl_do_cpuid(int cpu, cpuctl_cpuid_ar
 
 	/* Explicitly clear cpuid data to avoid returning stale info. */
 	bzero(data->data, sizeof(data->data));
-	DPRINTF("[cpuctl,%d]: retriving cpuid level %#0x for %d cpu\n",
-	    __LINE__, data->level, cpu);
+	DPRINTF("[cpuctl,%d]: retrieving cpuid lev %#0x type %#0x for %d cpu\n",
+	    __LINE__, data->level, data->level_type, cpu);
 	oldcpu = td->td_oncpu;
 	is_bound = cpu_sched_is_bound(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);
-	return (0);
+}
+
+static void
+cpuctl_do_cpuid(int cpu, cpuctl_cpuid_args_t *data, struct thread *td)
+{
+	cpuctl_cpuid_count_args_t cdata;
+
+	cdata.level = data->level;
+	/* Override the level type. */
+	cdata.level_type = 0;
+	cpuctl_do_cpuid_count(cpu, &cdata, td);
+	bcopy(cdata.data, data->data, sizeof(data->data)); /* Ignore error */
 }
 
 /*
@@ -271,12 +291,7 @@ cpuctl_do_update(int cpu, cpuctl_update_
 	    ("[cpuctl,%d]: bad cpu number %d", __LINE__, cpu));
 	DPRINTF("[cpuctl,%d]: XXX %d", __LINE__, cpu);
 
-	ret = cpuctl_do_cpuid(cpu, &args, td);
-	if (ret != 0) {
-		DPRINTF("[cpuctl,%d]: cannot retrive cpuid info for cpu %d",
-		    __LINE__, cpu);
-		return (ENXIO);
-	}
+	cpuctl_do_cpuid(cpu, &args, td);
 	((uint32_t *)vendor)[0] = args.data[1];
 	((uint32_t *)vendor)[1] = args.data[3];
 	((uint32_t *)vendor)[2] = args.data[2];

Modified: stable/10/sys/sys/cpuctl.h
==============================================================================
--- stable/10/sys/sys/cpuctl.h	Wed Jul  2 12:13:11 2014	(r268156)
+++ stable/10/sys/sys/cpuctl.h	Wed Jul  2 13:09:26 2014	(r268157)
@@ -35,11 +35,17 @@ typedef struct {
 } cpuctl_msr_args_t;
 
 typedef struct {
-	int		level;	/* CPUID level */
+	int		level;		/* CPUID level */
 	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;
 } cpuctl_update_args_t;
@@ -50,5 +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_count_args_t)
 
 #endif /* _CPUCTL_H_ */

Modified: stable/10/usr.sbin/cpucontrol/cpucontrol.8
==============================================================================
--- stable/10/usr.sbin/cpucontrol/cpucontrol.8	Wed Jul  2 12:13:11 2014	(r268156)
+++ stable/10/usr.sbin/cpucontrol/cpucontrol.8	Wed Jul  2 13:09:26 2014	(r268157)
@@ -65,6 +65,12 @@ device
 .Ek
 .Nm
 .Op Fl vh
+.Fl i Ar level,level_type
+.Bk
+.Ar device
+.Ek
+.Nm
+.Op Fl vh
 .Op Fl d Ar datadir
 .Fl u
 .Bk
@@ -114,6 +120,9 @@ In this case the inverted value of mask 
 .It Fl i Ar level
 Retrieve CPUID info.
 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
 Apply CPU firmware updates.
 The

Modified: stable/10/usr.sbin/cpucontrol/cpucontrol.c
==============================================================================
--- stable/10/usr.sbin/cpucontrol/cpucontrol.c	Wed Jul  2 12:13:11 2014	(r268156)
+++ stable/10/usr.sbin/cpucontrol/cpucontrol.c	Wed Jul  2 13:09:26 2014	(r268157)
@@ -99,6 +99,7 @@ static struct ucode_handler {
 static void	usage(void);
 static int	isdir(const char *path);
 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_update(const char *dev);
 static void	datadir_add(const char *path);
@@ -112,7 +113,7 @@ usage(void)
 	if (name == NULL)
 		name = "cpuctl";
 	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);
 }
 
@@ -170,6 +171,57 @@ do_cpuid(const char *cmdarg, const char 
 }
 
 static int
+do_cpuid_count(const char *cmdarg, const char *dev)
+{
+	char *cmdarg1, *endptr, *endptr1;
+	unsigned int level, level_type;
+	cpuctl_cpuid_count_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
 do_msr(const char *cmdarg, const char *dev)
 {
 	unsigned int msr;
@@ -414,7 +466,10 @@ main(int argc, char *argv[])
 	c = flags & (FLAG_I | FLAG_M | FLAG_U);
 	switch (c) {
 		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;
 		case FLAG_M:
 			error = do_msr(cmdarg, dev);


More information about the svn-src-all mailing list