svn commit: r267651 - in head: share/man/man4 sys/dev/cpuctl sys/sys usr.sbin/cpucontrol

Attilio Rao attilio at FreeBSD.org
Thu Jun 19 21:54:42 UTC 2014


Author: attilio
Date: Thu Jun 19 21:54:41 2014
New Revision: 267651
URL: http://svnweb.freebsd.org/changeset/base/267651

Log:
  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

Modified:
  head/share/man/man4/cpuctl.4
  head/sys/dev/cpuctl/cpuctl.c
  head/sys/sys/cpuctl.h
  head/usr.sbin/cpucontrol/cpucontrol.8
  head/usr.sbin/cpucontrol/cpucontrol.c

Modified: head/share/man/man4/cpuctl.4
==============================================================================
--- head/share/man/man4/cpuctl.4	Thu Jun 19 21:05:07 2014	(r267650)
+++ head/share/man/man4/cpuctl.4	Thu Jun 19 21:54:41 2014	(r267651)
@@ -86,19 +86,27 @@ Set/clear MSR bits according to the mask
 .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:
 .Bd -literal
 typedef struct {
-	int		level;	/* CPUID level */
+	int		level;		/* CPUID level */
+	int		level_type;	/* CPUID level type */
 	uint32_t	data[4];
 } cpuctl_cpuid_args_t;
 .Ed
 .Pp
 The
 .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
 field is used to store the received CPUID data.
 .It Dv CPUCTL_UPDATE cpuctl_update_args_t *args

Modified: head/sys/dev/cpuctl/cpuctl.c
==============================================================================
--- head/sys/dev/cpuctl/cpuctl.c	Thu Jun 19 21:05:07 2014	(r267650)
+++ head/sys/dev/cpuctl/cpuctl.c	Thu Jun 19 21:54:41 2014	(r267651)
@@ -69,6 +69,8 @@ static int cpuctl_do_msr(int cpu, cpuctl
     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,
+    struct thread *td);
 static int cpuctl_do_update(int cpu, cpuctl_update_args_t *data,
     struct thread *td);
 static int update_intel(int cpu, cpuctl_update_args_t *args,
@@ -177,6 +179,10 @@ 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:
+		ret = cpuctl_do_cpuid_count(cpu, (cpuctl_cpuid_args_t *)data,
+		    td);
+		break;
 	default:
 		ret = EINVAL;
 		break;
@@ -189,7 +195,7 @@ fail:
  * Actually perform cpuid operation.
  */
 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 oldcpu;
@@ -199,16 +205,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 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.
  */

Modified: head/sys/sys/cpuctl.h
==============================================================================
--- head/sys/sys/cpuctl.h	Thu Jun 19 21:05:07 2014	(r267650)
+++ head/sys/sys/cpuctl.h	Thu Jun 19 21:54:41 2014	(r267651)
@@ -35,7 +35,8 @@ typedef struct {
 } cpuctl_msr_args_t;
 
 typedef struct {
-	int		level;	/* CPUID level */
+	int		level;		/* CPUID level */
+	int		level_type;	/* CPUID level type */
 	uint32_t	data[4];
 } cpuctl_cpuid_args_t;
 
@@ -50,5 +51,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)
 
 #endif /* _CPUCTL_H_ */

Modified: head/usr.sbin/cpucontrol/cpucontrol.8
==============================================================================
--- head/usr.sbin/cpucontrol/cpucontrol.8	Thu Jun 19 21:05:07 2014	(r267650)
+++ head/usr.sbin/cpucontrol/cpucontrol.8	Thu Jun 19 21:54:41 2014	(r267651)
@@ -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: head/usr.sbin/cpucontrol/cpucontrol.c
==============================================================================
--- head/usr.sbin/cpucontrol/cpucontrol.c	Thu Jun 19 21:05:07 2014	(r267650)
+++ head/usr.sbin/cpucontrol/cpucontrol.c	Thu Jun 19 21:54:41 2014	(r267651)
@@ -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_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